home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSZIBM.ASM < prev   
Assembly Source File  |  1991-10-24  |  197KB  |  5,734 lines

  1.     NAME    mszibm
  2. ; File MSZIBM.ASM
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Terminal emulator module for IBM PC's and compatibles. Emulates Heath-19,
  9. ; VT52, VT102, and VT320. Original version for VT100 done by James Harvey,
  10. ; Indiana Purdue Univ, for MS Kermit 2.27. Taken from there by Joe Doupnik,
  11. ; Utah State Univ for MS Kermit 2.29 et seq.
  12. ; Edit history
  13. ; 6 Sept 1991 version 3.11
  14. ; Last edit 6 Sept 1991
  15. ; 20 July 1990 Include terminal type of VT100 as the same as VT102 but with
  16. ;  a different ident response. Also include terminal type of HONEYWELL VIP7809
  17. ;  as a VT100 with a VT100 ident response, with a canned response to ENQ, and
  18. ;  another to ESC y. Honeywell material is from Frank Dreano,
  19. ;  dreano@trout.nosc.mil.
  20. ; 29 May 1989 Rewrite and expand to DEC VT320 level. [jrd]
  21. ; 5 Oct 1988 Add controls to write from right to left, using bit vswdir in
  22. ;  the setup bytes vtemu.vtflgst and vtemu.vtflgop. The concept was invented
  23. ;  by Baruch Cochavy, IIT, Haifa, Israel; the current code is by [jrd].
  24. ;  If vswdir is non-zero writing is done starting on the visual right side.
  25. ;  Procedures direction and vtsclr accomdate most directional details. The
  26. ;  implementation here retains DX and CURSOR as logical values while the
  27. ;  physical screen coordinates are conditioned via proc direction and
  28. ;  several sections of special code. Screen printing is done full width if
  29. ;  writing right to left. Outside mszibm the logical cursor = physical. [jrd]
  30. ; 1 Jan 1988 version 2.30
  31. ;    [Joe R. Doupnik, Utah State Univ]
  32.  
  33.     public    anstty, ansini, ansrei, ansdsl, anskbi ; Entry points
  34.     public    ans52t, vsinit, tabset, tabclr, istabs
  35.     public    mar_top, mar_bot, anspflg, scroll, video_state ;  for msyibm
  36.     public    dnparam, dparam, dlparam, dninter, dinter, emubufc, emubuf
  37.     public    emubufl, dcsstrf, nrc2cp, cpdecsg, upss
  38.  
  39.  
  40. ; * Disclaimer *
  41. ;
  42. ; DEC and VT are trademarks of Digital Equipment Corporation.
  43. ;
  44. ; There is a naming convention
  45. ; for the ANSI and VT100 functions and flags; generally, the stuff in the
  46. ; symbol after "ans" or "at" is the function or mode mnemonic used in the
  47. ; VT100 manual.
  48. ; This was the first thing I ever wrote in 8088 assembler (some of it was
  49. ; stolen from MSYIBM), and one of the constraints was that the emulator
  50. ; should work with a vanilla PC with a monochrome monitor. Given these and
  51. ; other constraints, no attempt was made to implement the following VT100
  52. ; features: (1) Smooth scolling, (2) 132 column lines, (3) Auto repeat,
  53. ; (5) Interlace/no interlace, (6) Double-width/double-height lines. The
  54. ; escape sequences to set and reset these are recognized, but ignored.
  55. ;    - James A. Harvey, IUPUI Computing Services, DEC Systems Group
  56. ;
  57. ; * End of Disclamer *
  58. ; ---------------------------------------------------------------------------
  59. ;
  60. ; Description of the global entry points and calls on external routines
  61. ; needed by this emulator.                    [jrd]
  62. ;
  63. ; vsinit - start up routine called as Kermit initializes. Takes no arguments.
  64. ;       Sets up address pointers to tabs, reads default terminal parameters
  65. ;       reads current screen coloring. Examines and updates structure
  66. ;       "vtemu." which is how mssset communicates changed information
  67. ;       about many Set Term parameters; "flags." is a Kermit structure
  68. ;       carrying the other Set Term parameters.
  69. ; anstty - starting point for displaying a character, delivered in AL.
  70. ;       Returns when the display operation is completed and that may
  71. ;       take many many instructions. All normal "characters received by
  72. ;       the terminal" are provided by calling anstty with the char in AL.
  73. ; ansini - entry point to initialize the emulator. It requires information
  74. ;       from msy in four registers: the Kermit terminal routine flags
  75. ;       "yflags" (used mainly to sense debug mode and the mode line toggle)
  76. ;       "low_rgt" (bh = row, bl = column of the lower right display corner)
  77. ;       "lbaudtab" (index into baud rate table, for status reporting)
  78. ;       "lpartab" (index into parity table, for status reporting)
  79. ;       Ansini causes a full reset of the emulator, including screen 
  80. ;       clearing and a beep. Ansini is also called by msy in response to
  81. ;       sensing the Alt = key combination to fully reset the emulator.
  82. ; ansrei - entry point to reinitialize the emulator. Nearly the same as
  83. ;       ansini except operating flags, tabs, etc are retained from the
  84. ;       previous emulator session. Items which can be changed by Set Term
  85. ;       are examined and updated. The msy flags "yflags" are needed.
  86. ;       This is the warm-restart entry point used when connect mode
  87. ;       is reentered gracefully. The screen is cleared only if the coloring
  88. ;       has changed. The starting cursor location is whereever msy puts it.
  89. ; ansdsl - display "led" (status line) information. Invoked by msy when
  90. ;       the mode line is constructed so the emulator can write the 
  91. ;       terminal type and the VT100 led status lights when Connect mode
  92. ;       is started. Requires "yflags" from msy to sense whether the mode
  93. ;       line is to be shown.
  94. ; anskbi - a routine called by msy to notify the emulator that a character
  95. ;       is available from the keyboard. No character is read, just flag
  96. ;       ttkbi is set. This is actually used only to beep when the cursor
  97. ;       goes beyond column 72 and the margin bell flag is on.
  98. ; ans52t - called by msy to change terminal types "on the fly" without
  99. ;       fully updating all operating parameters and without losing setup
  100. ;       information. Msy senses the Alt minus key and calls ans52t with
  101. ;       no arguments. Ans52t cycles among terminal types.
  102. ; other modules in msy are called by this file to handle screen scrolling
  103. ;       mode line on/off, output to the serial port (reports), screen
  104. ;       particulars (location, cursor shape, blanking). The list is
  105. ;       the set of code extrn procedures below; all are in file msy.
  106. ;
  107. ; data exchange is directly with msy to assist in scrolling (varaibles
  108. ;       "mar_top", "mar_bot") and in sensing the non-connect
  109. ;       mode screen coloring ("scbattr"). Screen coloring controlled by
  110. ;       the emulator is not permitted to influence the non-connect mode
  111. ;       screens whereas the emulator attempts to use the regular Kermit
  112. ;       screen colors as defaults. The kind of terminal to emulate is
  113. ;       held in byte "flags.vtflg" which is set by Set Term and by this
  114. ;       module for global information within Kermit.
  115. ;
  116. ; Many things have been added or modified since James Harvey donated this
  117. ;       code to Columbia University for use in Kermit.              [jrd]
  118. ; Character sets in VT320 and VT102 modes:
  119. ;  ASCII ("B"/94)
  120. ;  ISO Latin-1 ("A"/96)
  121. ;  DEC UK-ASCII ("A"/94, available only in VT102 mode)
  122. ;  DEC Supplemental Graphics ("%5"/94),
  123. ;  DEC Technical Graphics (">"/94), an extension taken from the VT340,
  124. ;  DEC Special Graphics ("0"/94 and "2"/94)
  125. ;  ALT-ROM (Kermit specific, "1"/94/96)
  126. ;  DEC National Replacement Chars (all 12 sets)
  127. ;  Startup:
  128. ;   GL = G0 = G1 = ASCII (or ALT-ROM if selected by SET TERM CHAR ALT-ROM),
  129. ;   GR = G2 = G3 = ISO Latin-1.
  130. ;   When an NRC is selected by SET TERM CHAR <country> and enabled by
  131. ;   CSI ? 42 h the NRC table replaces G0..G3 at the time of selection. When
  132. ;   thus designated and selected incoming characters are forced to 7 bits and
  133. ;   8-bit Controls (outgoing) is turned off. No designation means no selection.
  134. ;  Selecting a character set with the wrong sized designator yields no action.
  135. ;
  136. ; References:
  137. ;  "PT200 Programmers Reference Guide", 1984, Prime Computer # DOC 8621-001P
  138. ;  "Video Terminal Model H19, Operation", 1979, Heath Company # 595-2284-05
  139. ;  "VT100 User's Guide", 2nd ed., Jan 1979, DEC # EK-VT100-UG
  140. ;  "Rainbow 100+/100B Terminal Emulation Manual", June 1984, DEC # QV069-GZ
  141. ;  "Installing and Using The VT320 Video Terminal", June 1987,
  142. ;    DEC # EK-VT320-UU-001
  143. ;  "VT320 Programmer Reference Manual", July 1987, DEC # EK-VT320-RM-001
  144. ;  "VT330/340 Programmer Ref Manual", 2nd ed, May 1988,
  145. ;    Vol 1: Text programming DEC # EK-VT3XX-TP-002
  146. ;    Vol 2: Graphics programming DEC # EK-VT3XX-GP-002
  147. ; ---------------------------------------------------------------------------
  148.  
  149.  
  150. swidth  equ     132            ; assumed max screen width
  151. slen    equ    60            ; assumed max screen length 
  152. maxparam equ    10            ; number of ESC and DCS Parameters
  153. maxinter equ    10            ; number of ESC and DCS Intermediates
  154. gsize    equ    128            ; character set storage size
  155.                     ; anspflg bit field definitions:
  156. ; prtscr equ    1            ; used in msyibm print screen toggle
  157. vtautop    equ    1            ; autoprint enabled (1)
  158. vtcntp    equ    2            ; controller print enabled (1)
  159. vtextp    equ    4            ; printer extent set (1)
  160. vtffp    equ    10h            ; form feed wanted at end of print (1)
  161.  
  162. h19l25    equ    1            ; h19stat, line 25 enabled
  163. h19alf    equ    2            ; h19stat, auto cr/lf when cr seen
  164.                     ; display save-info for dspstate
  165. dsptype    equ    1            ; main (0) or status line (1) flag
  166. dspdecom equ    2            ; remembered origin mode (1=on)
  167.  
  168. ; DEC emulator status flags (bits in words vtemu.vtflgst and vtemu.vtflgop)
  169. ;anslnm  equ    1H            ; ANSI line feed/new line mode
  170. ;decawm  equ    2H            ; DEC autowrap mode
  171. ;decscnm equ    80H            ; DEC screen mode
  172. ;decckm  equ    200H            ; DEC cursor keys mode
  173. ;deckpam equ    400H            ; DEC keypad application mode
  174. ;decom   equ    800H            ; DEC origin mode
  175. ;deccol     equ    1000H            ; DEC column mode (0=80 col)
  176. ;decanm  equ    2000H            ; ANSI mode
  177. ;dececho equ    4000H            ; ANSI local echo on (1 = on)
  178.      
  179. ; Terminal SETUP mode flags (joint with bits above, some name dups)
  180. ;vsnewline    equ    1H        ; ANSI new line (0 = off)
  181. ;vswrap        equ    2H        ; Line wrap around (0 = no wrap)
  182. ;vsnrcm        equ    4H        ; National Rep Char set (0=none)
  183. ;vswdir        equ    8H        ; Writing direction (0=left, 1 right)
  184. ;vskeyclick    equ    10H        ; Keyclick (0 = off)
  185. ;vsmarginbell    equ    20H        ; Margin bell (0 = off)
  186. ;vscursor    equ    40H        ; Cursor (0 = block, 1 = underline)
  187. ;vsscreen    equ    80H        ; Screen (0 = normal, 1 = rev. video)
  188. ;vscntl        equ    100h        ; 8 or 7 bit controls (1 = 8-bit)
  189.  
  190. ;vsdefaults    equ    0+vscursor
  191.  
  192. ; Kinds of terminals available
  193. ;ttgenrc equ    0            ; Type 0: no emulation done by Kermit
  194. ;ttheath equ    1            ; Type 1: Heath-19
  195. ;ttvt52    equ    2            ; Type 2: VT52
  196. ;ttvt100 equ    3            ; Type 3: VT100
  197. ;ttvt102 equ    4            ; Type 4: VT102
  198. ;ttvt320 equ    5            ; Type 5: VT320
  199. ;tttek    equ    6            ; Type 6: Tektronix 4010
  200. ;tthoney equ    7            ; Type 7: Honeywell VIP8708 (VT100)
  201. ;TTTYPES equ    8            ; Number of terminal types defined
  202.  
  203. ;emulst    struc        ; structure of vtemu.xxx for VTxxx emulator
  204. ;vtflgst dw    0    ; DEC setup flags (from SET)
  205. ;vtflgop dw    0    ; DEC runtime flags, like setup flags (here & STAT)
  206. ;vttbs    dw    0    ; pointer to default tab stops, for SET
  207. ;vttbst    dw    0    ; pointer to active tab stops, for STATUS
  208. ;vtchset db    1    ; value of default character set (1=US-ascii)
  209. ;att_ptr dw    0    ; pointer to normal & reverse video attributes
  210. ;emulst    ends
  211. ;;;;;;;;;;;;;;;;  end references ;;;;;;;;;;;;;;;;;;;;
  212.  
  213. data    segment
  214.     extrn    vtemu:byte, scbattr:byte, flags:byte, yflags:byte
  215.     extrn    crt_lins:byte, crt_cols:byte, rxtable:byte, denyflg:word
  216.     extrn    tekflg:byte, vtclear:byte, dosnum:word, chcontrol:byte
  217.     extrn    parstate:word, pardone:word, parfail:word, nparam:word,
  218.     extrn    param:word, lparam:byte, ninter:word, inter:byte, ttyact:byte
  219.     extrn    L1cp437:byte, L1cp850:byte, L1cp860:byte, L1cp863:byte
  220.     extrn    L1cp865:byte
  221.     even                    ; C0 7-bit control code table
  222. ansc0    dw    5 dup (atign)            ; NUL, SOH, STX, ETX, EOT
  223.     dw    atenq,atign,vtbell,atbs,atht     ; ENQ, ACK, BEL, BS,  HT
  224.     dw    atlf, atlf, atff, atcr,atls1    ; LF,  VT,  FF,  CR,  SO
  225.     dw    atls0, 4 dup (atign)        ; SI,  DLE, DC1, DC2, DC3
  226.     dw    4 dup (atign), atcan        ; DC4, NAK, SYN, ETB, CAN
  227.     dw    atign, atnrm, atesc,atign,atign    ; EM,  SUB, ESC, FS,  GS
  228.     dw    2 dup (atign)            ; RS,  US
  229.  
  230.                         ; C1 8-bit control code table
  231. ansc1    dw    4 dup (atign),atind        ; ignore 4, IND
  232.     dw    atnel,atign,atign,athts,atign    ; NEL, SSA, ESA, HTS, HTJ
  233.     dw    atign,atign,atign,atri, atign    ; VTS, PLD, PLU, RI,  SS2
  234.     dw    atign,atdcs,3 dup (atign)    ; SS3, DCS, PU1, PU2, STS
  235.     dw    5 dup (atign)            ; CCH, MW,  SPA, EPA, ignore
  236.     dw    atign,atign,atcsi,atgotst,atdcsnul; ignore 2, CSI, ST, OSC
  237.     dw    2 dup (atdcsnul)        ; PM,  APC
  238.  
  239. ; Heath-19 mode escape follower table
  240. h19esc    db    36            ; number of entries
  241.     dw    h19ejt            ; address of action routines
  242.     db    '<=>@A','BCDEF','GHIJK','LMNOY','Z[bjk','lnopq','rvwxy','z'
  243.  
  244. ; Dispatch table for Heath-19 escape sequence table h19esc
  245.     even
  246. h19ejt    dw    h19sans, atkpam,  atkpnm,  entins,  atcuu    ; '<=>@A'
  247.     dw    atcud,   atcuf,   atcub,   h19clrs, v52sgm    ; 'BCDEF'
  248.     dw    chrdef,  atcup,   atri0,   ated,    atel    ; 'GHIJK'
  249.     dw    inslin,  dellin,  atdelc,  noins,   v52pos    ; 'LMNOY'
  250.     dw    decid,   h19csi,  h19esos, h19sc,   h19rc    ; 'Z[bjk'
  251.     dw    h19erl,  hrcup,   h19ero,  h19herv, h19hxrv    ; 'lnopq'
  252.     dw    atnorm,  h19wrap, h19nowrp,h19smod, h19cmod    ; 'rvwxy'
  253.     dw    atxreset                    ; 'z'
  254.  
  255. h19ans    db    21            ; Heath-19 ANSI style escape sequences
  256.     dw    h19jmp            ; address of action routine table
  257.     db    'ABCDH','JKLMP','fhlmn','pqrsu','z'
  258.  
  259. ; Heath-19 action table for h19ans
  260.     even
  261. h19jmp    dw    atcuu, atcud, atcuf,  atcub,  atcup        ; 'ABCDH'
  262.     dw    h19ed, atel,  inslin, dellin, atdelc        ; 'JKLMP'
  263.     dw    atcup, atsm,  atrm,   atsgr,  rpcup        ; 'fhlmn'
  264.     dw    atign, atign, atign,  h19sc,  h19rc        ; 'pqrsu'
  265.     dw    atxreset                    ; 'z'
  266.  
  267. ; VT52 compatibility mode escape follower table
  268. v52esc    db    23            ; number of entries
  269.     dw    v52ejt            ; address of action routines
  270.     db    '78<=>', 'ABCDF', 'GHIJK', 'VWXYZ'
  271.     db    ']',5eh,5fh        ; 5eh = caret, 5fh = underscore
  272.  
  273. ; Dispatch for v52esc table
  274.     even
  275. v52ejt    dw    atsc,   atrc,   v52ans, atkpam, atkpnm        ; '78<=>'
  276.     dw    atcuu,  atcud,  atcuf,  atcub,  v52sgm        ; 'ABCDF'
  277.     dw    chrdef, atcup,  atri0,  ated,   atel        ; 'GHIJK'
  278.     dw    v52pl,  v52pcb, v52pce, v52pos, decid        ; 'VWXYZ'
  279.     dw    v52ps,  v52pcb, v52pce                ; ']^_'
  280.  
  281. ; VT320/VT102/VT100/Honewell ANSI mode escape follower table
  282. ansesc    db    43            ; number of entries
  283.     dw    ansejt            ; address of action routines
  284.     db    '01234','5678<','=>?AB','CDEFG','HKMNO','PQRYZ'
  285.     db    '[\]',5eh,5fh        ; 5eh = caret, 5fh=underscore
  286.     db    60h,'cno',7bh        ; 7bh=left curly brace,  7ch=vert bar
  287.     db    7ch,7dh,7eh        ; 7dh=right curly brace, 7eh=tilde
  288.  
  289. ; Dispatch for ansesc table
  290.     even
  291. ansejt    dw    atdgf0, atdgf1, atdgf0, atsdhl, atsdhl         ; '01234'
  292.     dw    4 dup (atsdhl), atdgfu                ; '5678<'
  293.     dw    atkpam, atdgft, atdgfq, atdgfA, atdgfB         ; '=>?AB'
  294.     dw    atdgnrc, atind0, atnel0,ats7c,  ats8c        ; 'CDEFG'
  295.     dw    athts0, atdgnrc, atri0, atss2, atss3        ; 'HKMNO'
  296.     dw    atdcs0, atdgnrc, atdgnrc, decid, atdgnrc    ; 'PQRYZ'
  297.     dw    atcsi0, atgotst0, 3 dup (atdcsnul0)        ; '[\]^_'
  298.     dw    athoncls,atxreset,atls2, atls3,    atpriv        ; '`cno{'
  299.     dw    atls3r, atls2r, atls1r                ; '|}~'
  300.  
  301. ; Final char table for VT320/VT102/VT100/Honeywell ANSI control sequences
  302. anstab    db    38            ; number of entries
  303.     dw    ansjmp            ; address of action routines
  304.     db    '@ABCD','EFGHI','JKLMP', 'Xacde','fghil','mnpqr','uwxyz'
  305.     db    7ch,7dh,7eh        ; 7dh=right curly brace, 7eh=tilde
  306.  
  307. ; Dispatch for anstab table
  308.     even
  309. ansjmp    dw    ansich, atcuu,  atcud,  atcuf,  atcub        ; '@ABCD'
  310.     dw    atcnl,  atcpl,  atcha,  atcup,  atcht        ; 'EFGHI'
  311.     dw    ated,   atel,   inslin, dellin, atdelc        ; 'JKLMP'
  312.     dw    atech,  atcuf,  atda,   atcva,    atcud          ; 'Xacde'
  313.     dw    atcup,  attbc,  atsm,   ansprt, atrm        ; 'fghil'
  314.     dw    atsgr,  atdsr,  decscl, atll,   atstbm        ; 'mnpqr'
  315.     dw    atrqtsr,atrqpsr,atreqt, atctst, atxreset    ; 'uwxyz'
  316.     dw    atscpp, atsasd, atssdt                ; '|}~'
  317.  
  318. ; Final character table for Device Control Strings (DCS, ESC P)
  319. dcstab    db    5            ; number of entries
  320.     dw    dcsjmp            ; address of action routines
  321.     db    'pqu',7bh,7ch        ; 7bh = left curly brace
  322.  
  323. ; Dispatch for dcstab table
  324.     even
  325. dcsjmp    dw    atcrqq, atcrq, atupss, atdcsnul, atudk        ; 'pqu{|'
  326. ;;; DCS Ps $ p string ST   page 209 restore color palette
  327.  
  328. ; Heath-19 special graphics characters to CP437. Use as offsets from caret
  329. ; (94D)
  330. hgrtab    db    249, 17,179,196,197    ; caret,underscore,accent grave,a,b
  331.     db    191,217,192,218,241    ; c,d,e,f,g
  332.     db     26,177,219, 25,220    ; h,i,j,k,l
  333.     db    220,223,223,223,222    ; m,n,o,p,q
  334.     db     16,194,180,193,195    ; r,s,t,u,v
  335.     db    'X','/','\',223,220    ; w,x,y,z,left curly brace
  336.     db    221,222, 20        ; vertical bar,right curly brace,tilde
  337. hgrtabl    equ ($-hgrtab)
  338.  
  339. ; VT320/VT102 "Special graphics" set translation table for characters 95..126d
  340. ; when the special graphics set is selected. Some characters (98, 99, 100,
  341. ; 101, 104, 105, 111, 112, 114, 115, and 116) do not have exact equivalents
  342. ; in the available set on the IBM, so a close substitution is made.
  343. ; Table is indexed by ASCII char value minus 95 for chars 95..126d.
  344. sgrtab    db     32,  4,177, 26, 23,  27, 25,248,241, 21
  345.     db     18,217,191,218,192, 197,196,196,196,196
  346.     db    196,195,180,193,194, 179,243,242,227,157
  347.     db    156,250
  348. sgrtabl    equ    $-sgrtab
  349.  
  350.     ; DEC National Replacement Char sets, one table for each Code Page
  351.                         ; CP437
  352. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  353. nrc437    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  354.     db    5fh,60h,7bh,7ch,7dh,7eh
  355.     db    94,'B',0            ; 94 byte set, letter pair
  356.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  357.     db    5fh,60h,7bh,7ch,7dh,7eh
  358.     db    94,'A',0
  359.     db    9ch,3fh,98h,0abh,7ch,5eh    ; 2, Dutch, "4"
  360.     db    5fh,60h,22h,9fh,0ach,27h
  361.     db    94,'4',0
  362.     db    23h,40h,8eh,99h,8fh,9ah        ; 3, Finnish, "5"
  363.     db    5fh,82h,84h,94h,86h,81h
  364.     db    94,'5',0
  365.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  366.     db    5fh,60h,82h,97h,8ah,22h
  367.     db    94,'R',0
  368.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  369.     db    5fh,93h,82h,97h,8ah,96h
  370.     db    94,'9',0
  371.     db    23h,15h,8eh,99h,9ah,5eh        ; 6, German, "K"
  372.     db    5fh,60h,84h,94h,81h,0e1h
  373.     db    94,'K',0
  374.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  375.     db    5fh,97h,85h,95h,8ah,8dh
  376.     db    94,'Y',0
  377.     db    23h,40h,92h,0edh,8fh,5eh    ; 8, Norwegian/Danish, "`"
  378.     db    5fh,60h,91h,0edh,86h,7eh
  379.     db    94,60h,0
  380.     db    23h,40h,8eh,80h,99h,5eh        ; 9, Portugese, "%6"
  381.     db    5fh,60h,0a6h,87h,0a7h,7eh
  382.     db    94,'%','6'
  383.     db    9ch,15h,8ch,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  384.     db    5fh,60h,0f8h,0a4h,87h,7eh
  385.     db    94,'Z',0
  386.     db    23h,90h,8eh,99h,8fh,9ah        ; 11, Swedish, "7"
  387.     db    5fh,82h,84h,94h,86h,81h
  388.     db    94,'7',0
  389.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  390.     db    8ah,93h,84h,94h,81h,96h
  391.     db    94,'=',0
  392.  
  393.                         ; CP850
  394. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  395. nrc850    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  396.     db    5fh,60h,7bh,7ch,7dh,7eh
  397.     db    94,'B',0            ; 94 byte set, letter pair
  398.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  399.     db    5fh,60h,7bh,7ch,7dh,7eh
  400.     db    94,'A',0
  401.     db    9ch,0f3h,98h,0abh,7ch,5eh    ; 2, Dutch, "4"
  402.     db    5fh,60h,22h,9fh,0ach,27h
  403.     db    94,'4',0
  404.     db    23h,40h,8eh,99h,8fh,9ah        ; 3, Finnish, "5"
  405.     db    5fh,82h,84h,94h,86h,81h
  406.     db    94,'5',0
  407.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  408.     db    5fh,60h,82h,97h,8ah,22h
  409.     db    94,'R',0
  410.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  411.     db    5fh,93h,82h,97h,8ah,96h
  412.     db    94,'9',0
  413.     db    23h,15h,8eh,99h,9ah,5eh        ; 6, German, "K"
  414.     db    5fh,60h,84h,94h,81h,0e1h
  415.     db    94,'K',0
  416.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  417.     db    5fh,97h,85h,95h,8ah,8dh
  418.     db    94,'Y',0
  419.     db    23h,40h,92h,09dh,8fh,5eh    ; 8, Norwegian/Danish, "`"
  420.     db    5fh,60h,91h,09bh,86h,7eh
  421.     db    94,60h,0
  422.     db    23h,40h,0b5h,80h,0e5h,5eh    ; 9, Portugese, "%6"
  423.     db    5fh,60h,61h,87h,0e4h,7eh
  424.     db    94,'%','6'
  425.     db    9ch,15h,0adh,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  426.     db    5fh,60h,0f8h,0a4h,87h,7eh
  427.     db    94,'Z',0
  428.     db    23h,90h,8eh,99h,8fh,9ah        ; 11, Swedish, "7"
  429.     db    5fh,82h,84h,94h,86h,81h
  430.     db    94,'7',0
  431.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  432.     db    8ah,93h,84h,94h,81h,96h
  433.     db    94,'=',0
  434.                         ; CP860
  435. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  436. nrc860    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  437.     db    5fh,60h,7bh,7ch,7dh,7eh
  438.     db    94,'B',0            ; 94 byte set, letter pair
  439.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  440.     db    5fh,60h,7bh,7ch,7dh,7eh
  441.     db    94,'A',0
  442.     db    9ch,3fh,79h,0abh,7ch,5eh    ; 2, Dutch, "4"
  443.     db    5fh,60h,22h,3fh,0ach,27h
  444.     db    94,'4',0
  445.     db    23h,40h,41h,4fh,41h,9ah        ; 3, Finnish, "5"
  446.     db    5fh,82h,61h,6fh,61h,81h
  447.     db    94,'5',0
  448.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  449.     db    5fh,60h,82h,97h,8ah,22h
  450.     db    94,'R',0
  451.     db    23h,85h,83h,87h,88h,69h        ; 5, French Canadian, "9"
  452.     db    5fh,93h,82h,97h,8ah,75h
  453.     db    94,'9',0
  454.     db    23h,15h,41h,4fh,9ah,5eh        ; 6, German, "K"
  455.     db    5fh,60h,61h,6fh,81h,0e1h
  456.     db    94,'K',0
  457.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  458.     db    5fh,97h,85h,95h,8ah,8dh
  459.     db    94,'Y',0
  460.     db    23h,40h,3fh,0edh,41h,5eh    ; 8, Norwegian/Danish, "`"
  461.     db    5fh,60h,3fh,0edh,61h,7eh
  462.     db    94,60h,0
  463.     db    23h,40h,8eh,80h,99h,5eh        ; 9, Portugese, "%6"
  464.     db    5fh,60h,84h,87h,94h,7eh
  465.     db    94,'%','6'
  466.     db    9ch,15h,0adh,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  467.     db    5fh,60h,0f8h,0a4h,87h,7eh
  468.     db    94,'Z',0
  469.     db    23h,90h,41h,4fh,41h,9ah        ; 11, Swedish, "7"
  470.     db    5fh,82h,61h,6fh,61h,75h
  471.     db    94,'7',0
  472.     db    97h,85h,82h,87h,88h,69h        ; 12, Swiss, "="
  473.     db    8ah,93h,61h,6fh,81h,75h
  474.     db    94,'=',0
  475.                         ; CP863
  476. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  477. nrc863    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  478.     db    5fh,60h,7bh,7ch,7dh,7eh
  479.     db    94,'B',0            ; 94 byte set, letter pair
  480.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  481.     db    5fh,60h,7bh,7ch,7dh,7eh
  482.     db    94,'A',0
  483.     db    9ch,0adh,79h,0abh,7ch,5eh    ; 2, Dutch, "4"
  484.     db    5fh,60h,0a4h,9fh,0ach,0a1h
  485.     db    94,'4',0
  486.     db    23h,40h,41h,4fh,41h,55h        ; 3, Finnish, "5"
  487.     db    5fh,82h,61h,6fh,61h,81h
  488.     db    94,'5',0
  489.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  490.     db    5fh,60h,82h,97h,8ah,0a4h
  491.     db    94,'R',0
  492.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  493.     db    5fh,93h,82h,97h,8ah,96h
  494.     db    94,'9',0
  495.     db    23h,15h,41h,4fh,9ah,5eh        ; 6, German, "K"
  496.     db    5fh,60h,61h,6fh,81h,0e1h
  497.     db    94,'K',0
  498.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  499.     db    5fh,97h,6fh,85h,8ah,69h
  500.     db    94,'Y',0
  501.     db    23h,40h,3fh,0edh,41h,5eh    ; 8, Norwegian/Danish, "`"
  502.     db    5fh,60h,0efh,0edh,61h,7eh
  503.     db    94,60h,0
  504.     db    23h,40h,41h,80h,4fh,5eh        ; 9, Portugese, "%6"
  505.     db    5fh,60h,61h,87h,6fh,7eh
  506.     db    94,'%','6'
  507.     db    9ch,15h,3fh,4eh,3fh,5eh        ; 10, Spanish, "Z"
  508.     db    5fh,60h,0f8h,6eh,87h,7eh
  509.     db    94,'Z',0
  510.     db    23h,90h,41h,4fh,41h,9ah        ; 11, Swedish, "7"
  511.     db    5fh,82h,61h,6fh,61h,81h
  512.     db    94,'7',0
  513.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  514.     db    8ah,93h,61h,6fh,81h,96h
  515.     db    94,'=',0
  516.                         ; CP865
  517. ; 12 replacment bytes (keyed by ASCII bytes), NRC number, country, size, ident
  518. nrc865    db    23h,40h,5bh,5ch,5dh,5eh        ; 0, ASCII, "B", dispatch ref
  519.     db    5fh,60h,7bh,7ch,7dh,7eh
  520.     db    94,'B',0            ; 94 byte set, letter pair
  521.     db    9ch,40h,5bh,5ch,5dh,5eh        ; 1, British, "A"
  522.     db    5fh,60h,7bh,7ch,7dh,7eh
  523.     db    94,'A',0
  524.     db    9ch,3fh,98h,0abh,7ch,5eh    ; 2, Dutch, "4"
  525.     db    5fh,60h,22h,9fh,0ach,27h
  526.     db    94,'4',0
  527.     db    23h,40h,8eh,99h,8fh,9ah        ; 3, Finnish, "5"
  528.     db    5fh,82h,84h,94h,86h,81h
  529.     db    94,'5',0
  530.     db    9ch,85h,0f8h,87h,15h,5eh    ; 4, French, "R"
  531.     db    5fh,60h,82h,97h,8ah,22h
  532.     db    94,'R',0
  533.     db    23h,85h,83h,87h,88h,8ch        ; 5, French Canadian, "9"
  534.     db    5fh,93h,82h,97h,8ah,96h
  535.     db    94,'9',0
  536.     db    23h,15h,8eh,99h,9ah,5eh        ; 6, German, "K"
  537.     db    5fh,60h,84h,94h,81h,0e1h
  538.     db    94,'K',0
  539.     db    9ch,15h,0f8h,87h,82h,5eh    ; 7, Italian, "Y"
  540.     db    5fh,97h,85h,95h,8ah,8dh
  541.     db    94,'Y',0
  542.     db    23h,40h,92h,9dh,8fh,5eh        ; 8, Norwegian/Danish, "`"
  543.     db    5fh,60h,91h,9bh,86h,7eh
  544.     db    94,60h,0
  545.     db    23h,40h,41h,80h,4fh,5eh        ; 9, Portugese, "%6"
  546.     db    5fh,60h,61h,87h,6fh,7eh
  547.     db    94,'%','6'
  548.     db    9ch,15h,0adh,0a5h,0a8h,5eh    ; 10, Spanish, "Z"
  549.     db    5fh,60h,0f8h,0a4h,87h,7eh
  550.     db    94,'Z',0
  551.     db    23h,90h,8eh,99h,8fh,9ah        ; 11, Swedish, "7"
  552.     db    5fh,82h,84h,94h,86h,81h
  553.     db    94,'7',0
  554.     db    97h,85h,82h,87h,88h,8ch        ; 12, Swiss, "="
  555.     db    8ah,93h,84h,94h,81h,96h
  556.     db    94,'=',0
  557.  
  558. nrcfinal db    'A45CR9QKY`E6Z7H='        ; NRC country letters
  559. nrcflen    equ    $-nrcfinal            ; "%6" Port. done separately
  560. nrcnum    db    1,2,3,3,4,5,5,6,7,8,8,8,10,11,11,12 ; country numbers matching
  561.                         ; nrcfinal letters
  562.  
  563. ;NRC to DEC keyboard codes, North American (ASCII is nrckbd 1),+ALT-ROM+transp
  564. nrckbd    db    1,2,8,6,14,4,7,9,13,16,15,12,11,1,1,1
  565.  
  566. ; Translation tables for byte codes 0a0h..0ffh to map DEC Multinational
  567. ; Character Set (DEC Supplemental Graphic) to Code Pages.
  568. ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
  569. ; considered to be a control code, 80h..9fh are 8-bit controls (C1).
  570. ; Each table is 128 translatable bytes followed by the table size (94) and the
  571. ; ISO announcer ident '%5'.
  572.                     ; from DEC Multinational to Code Page
  573.                             ; to CP437
  574. MNcp437    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  575.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  576.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  577.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  578.     db    0h,0adh,9bh,9ch,   20h,9dh,20h,15h    ; column 10
  579.     db    0fh,40h,0a6h,0aeh, 20h,20h,20h,20h
  580.     db    0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0fah    ; column 11
  581.     db    20h,31h,0a7h,0afh, 0ach,0abh,20h,0a8h
  582.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  583.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  584.     db    20h,0a5h,4fh,4fh,  4fh,4fh,99h,4fh    ; column 13
  585.     db    4fh,55h,55h,55h,   9ah,59h,20h,0e1h
  586.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  587.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  588.     db    20h,0a4h,95h,0a2h, 93h,6fh,94h,6fh    ; column 15
  589.     db    6fh,97h,0a3h,96h,  81h,98h,20h,0h
  590.     db    94,'%','5'            ; 94 byte set, letter ident
  591.  
  592.                             ; to CP850
  593. MNcp850    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  594.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  595.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  596.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  597.     db    0h,0adh,0bdh,9ch,  20h,0beh,20h,0f5h    ; column 10
  598.     db    0cfh,0b8h,0a6h,0aeh, 20h,20h,20h,20h
  599.     db    0f8h,0f1h,0fdh,0fch, 20h,0e6h,0f4h,0fah    ; column 11
  600.     db    20h,0fbh,0a7h,0afh, 0ach,0abh,20h,0a8h
  601.     db    0b7h,0b5h,0b6h,0c7h, 8eh,8fh,92h,80h    ; column 12
  602.     db    0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
  603.     db    20h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,4fh    ; column 13
  604.     db    9dh,0ebh,0e9h,0eah, 9ah,0edh,20h,0e1h
  605.     db    85h,0a0h,83h,0c6h,  84h,86h,91h,87h    ; column 14
  606.     db    8ah,82h,88h,89h,    8dh,0a1h,8ch,8bh
  607.     db    20h,0a4h,95h,0a2h,  93h,0e4h,94h,6fh    ; column 15
  608.     db    9bh,97h,0a3h,96h,   81h,98h,20h,0h
  609.     db    94,'%','5'            ; 94 byte set, letter ident
  610.                             ; to CP860
  611. MNcp860    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  612.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  613.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  614.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  615.     db    0h,0adh,9bh,9ch,   20h,59h,20h,15h    ; column 10
  616.     db    0fh,40h,0a6h,0aeh, 20h,20h,20h,20h
  617.     db    0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0fah    ; column 11
  618.     db    20h,31h,0a7h,0afh, 0ach,0abh,20h,0a8h
  619.     db    91h,86h,8fh,8eh,   41h,41h,41h,80h    ; column 12
  620.     db    92h,90h,89h,45h,   8bh,98h,49h,49h
  621.     db    20h,0a5h,0a9h,9fh, 8ch,99h,4fh,4fh    ; column 13
  622.     db    4fh,9dh,96h,55h,   9ah,59h,20h,0e1h
  623.     db    85h,0a0h,83h,84h,  61h,61h,61h,87h    ; column 14
  624.     db    8ah,82h,88h,65h,   8dh,0a1h,69h,69h
  625.     db    20h,0a4h,95h,0a2h, 93h,94h,6fh,6fh    ; column 15
  626.     db    6fh,97h,0a3h,75h,  81h,79h,20h,0h
  627.     db    94,'%','5'            ; 94 byte set, letter ident
  628.                             ; to CP863
  629. MNcp863    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  630.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  631.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  632.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  633.     db    0h,3fh,9bh,9ch,    20h,59h,20h,8fh    ; column 10
  634.     db    98h,40h,61h,0aeh,  20h,20h,20h,20h
  635.     db    0f8h,0f1h,0fdh,0a6h, 20h,0e6h,86h,0fah    ; column 11
  636.     db    20h,31h,6fh,0afh,  0ach,0abh,20h,3fh
  637.     db    8eh,41h,84h,41h,   41h,41h,41h,80h    ; column 12
  638.     db    91h,90h,92h,94h,   49h,49h,0a8h,95h
  639.     db    20h,4eh,4fh,4fh,   99h,4fh,4fh,4fh    ; column 13
  640.     db    4fh,9dh,55h,9eh,   9ah,59h,20h,0e1h
  641.     db    85h,61h,83h,61h,   61h,61h,61h,87h    ; column 14
  642.     db    8ah,82h,88h,89h,   69h,69h,8ch,8bh
  643.     db    20h,6eh,6fh,0a2h,  93h,6fh,6fh,6fh    ; column 15
  644.     db    6fh,97h,0a3h,96h,  81h,79h,20h,0h
  645.     db    94,'%','5'            ; 94 byte set, letter ident
  646.                             ; to CP865
  647. MNcp865    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  648.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  649.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  650.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  651.     db    0h,0adh,3fh,9ch,   20h,59h,20h,15h    ; column 10
  652.     db    0afh,40h,0a6h,0aeh, 20h,20h,20h,20h
  653.     db    0f8h,0f1h,0fdh,33h, 20h,0e6h,14h,0fah    ; column 11
  654.     db    20h,31h,0a7h,03fh, 0ach,0abh,20h,0a8h
  655.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  656.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  657.     db    20h,0a5h,4fh,4fh,  4fh,4fh,99h,4fh    ; column 13
  658.     db    9dh,55h,55h,55h,   9ah,59h,20h,0e1h
  659.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  660.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  661.     db    20h,0a4h,95h,0a2h, 93h,6fh,94h,6fh    ; column 15
  662.     db    9bh,97h,0a3h,96h,  81h,79h,20h,0h
  663.     db    94,'%','5'            ; 94 byte set, letter ident
  664.  
  665. ; 128 byte translation tables from Code Pages to DEC Multinational char set
  666. ; (DEC Supplemental Graphic). For GRight only (high bit set).
  667.                             ; from Code Page 437
  668. cp437MN    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  669.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  670.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  671.     db    0fdh,0d6h,0dch,0a2h, 0a3h,0a5h,3fh,3fh
  672.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  673.     db    0bfh,3fh,3fh,0bdh,   0bch,0a1h,0abh,0bbh
  674.     db    16 dup (3fh)                 ; column 11
  675.     db    16 dup (3fh)                 ; column 12
  676.     db    16 dup (3fh)                 ; column 13
  677.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  678.     db    5 dup(3fh),            0f8h,3fh,3fh
  679.     db    3fh,0b1h, 4 dup (3fh),         3fh,3fh ; column 15
  680.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  681.                              ; from Code Page 850
  682. cp850MN    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  683.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  684.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  685.     db    0fdh,0d6h,0dch,0f8h, 0a3h,0d8h,58h,3fh
  686.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  687.     db    0bfh,3fh,3fh,0bdh,   0bch,0a1h,0abh,0bbh
  688.     db    5 dup (3fh),              0c1h,0c2h,0c0h ; column 11
  689.     db    0a9h, 4 dup (3fh),       0a2h,0a5h,3fh
  690.     db    6 dup (3fh),0e3h,0c3h,  7 dup (3fh),0a8h ; column 12
  691.     db    3fh,3fh,0cah,0cbh,   0c8h,0b9h,0cdh,0ceh ; column 13
  692.     db    0cfh, 4 dup (3fh),       7ch,0cch,3fh
  693.     db    0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,3fh  ; column 14
  694.     db    3fh,0dah,0dbh,0d9h,  79h,59h,2dh,27h
  695.     db    2dh,0b1h,3dh,3fh,    0b6h,0a7h,3fh,2ch     ; column 15
  696.     db    0b0h,22h,0b7h,0b9h,  0b3h,0b2h,3fh,20h
  697.                              ; from Code Page 860
  698. cp860MN    db    0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
  699.     db    0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
  700.     db    0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
  701.     db    0cdh,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
  702.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  703.     db    0bfh,0d2h,3fh,0bdh,  0bch,0a1h,0abh,0bbh
  704.     db    16 dup (3fh)                 ; column 11
  705.     db    16 dup (3fh)                 ; column 12
  706.     db    16 dup (3fh)                 ; column 13
  707.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  708.     db    5 dup(3fh),            0f8h,3fh,3fh
  709.     db    3fh,0b1h, 4 dup (3fh),         3fh,3fh ; column 15
  710.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  711.                              ; from Code Page 863
  712. cp863MN    db    0c7h,0fch,0e9h,0e2h, 0c2h,0e0h,0b6h,0e7h ; column 8
  713.     db    0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
  714.     db    0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0f9h ; column 9
  715.     db    0a8h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
  716.     db    7ch,27h,0f3h,0fah,   22h,2ch,0b3h,2dh     ; column 10
  717.     db    0ceh,3fh,3fh,0bdh,   0bch,3fh,0abh,0bbh
  718.     db    16 dup (3fh)                 ; column 11
  719.     db    16 dup (3fh)                 ; column 12
  720.     db    16 dup (3fh)                 ; column 13
  721.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  722.     db    5 dup(3fh),            0f8h,3fh,3fh
  723.     db    3fh,0b1h, 4 dup (3fh),         3fh,3fh ; column 15
  724.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  725.                                   ; from Code Page 865
  726. cp865MN    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  727.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  728.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  729.     db    0fdh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  730.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  731.     db    0bfh,3fh,3fh,0bdh,   0bch,0a1h,0abh,0a8h
  732.     db    16 dup (3fh)                 ; column 11
  733.     db    16 dup (3fh)                 ; column 12
  734.     db    16 dup (3fh)                 ; column 13
  735.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  736.     db    5 dup(3fh),            0f8h,3fh,3fh
  737.     db    3fh,0b1h, 4 dup (3fh),         3fh,3fh ; column 15
  738.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  739.  
  740.                ; Dec Technical set to CP437, CP860, CP863, CP865
  741.              ; Note: CP850 lacks the symbols so expect trash
  742. dectech    db    32 dup (0)                ; columns 8 and 9
  743.     db    0h,0fbh,0dah,0c4h, 0f4h,0f5h,0b3h,0dah    ; column 10
  744.     db    0c0h,0bfh,0d9h,28h,28h,29h,29h,0b4h
  745.     db    0c3h,3ch,3eh,5ch,  2fh,0bfh,0d9h,03eh    ; column 11
  746.     db    0a8h,20h,20h,20h,  0f3h,3dh,0f2h,3fh
  747.     db    1eh,0ech,0ech,0f6h,1eh,1fh,0e8h,0e2h    ; column 12
  748.     db    0f7h,0f7h,0e9h,58h,3fh,1dh,1ah,0f0h
  749.     db    0e3h,3fh,20h,0e4h, 20h,20h,0fbh,0eah    ; column 13
  750.     db    3fh,54h,3fh,3fh,   0efh,55h,5eh,76h
  751.     db    0aah,0e0h,0e1h,78h,0ebh,0eeh,0edh,3fh    ; column 14 
  752.     db    6eh,69h,0e9h,6bh,  3fh,20h,76h,3fh
  753.     db    0e3h,3fh,70h,0e5h, 0e7h,0a8h,9fh,77h    ; column 15
  754.     db    45h,76h,3fh,1bh,   18h,1ah,19h,7fh
  755.     db    94,3eh,0            ; 94 byte set, letter ident
  756.  
  757. ; Device attributes response string. A VT100 reports as ESC [ ? 1 ; 2 c 
  758. ; Make strings asciiz.
  759. v32str    db    escape,'[?63;1;2;4;8;9;15c',0; VT320, level 3,
  760.         ; 132 col, printer, Sixel graphics, UDkeys,NRC,DEC Tech Chars
  761. v32sda    db    escape,'[>24;0;0c',0    ; VT320 secondary DA response
  762. v22str    db    escape,'[?62;1;2;4;8;9;15c',0; VT220, level 2, etc as above
  763. v102str    db    escape,'[?6c',0        ; VT102
  764. v100str db    escape,'[?1c',0        ; vanilla VT100
  765. v52str    db    escape,'/Z',0        ; VT100 in VT52 compatibility mode
  766. h19str    db    escape,'/K',0        ; Heath-19 (says plain VT52)
  767. VIPstr    db    escape,'[8p  OT',03h,escape,'[y7813  P GC  A ',03h
  768. VIPstrl    equ    $-VIPstr        ; Honeywell MOD400 3.1 id for ESC [ y
  769. ENQstr    db    '7813  P GC  A',03h    ; Honeywell MOD400 4.0 id string
  770. ENQstrl    equ    $-ENQstr
  771.  
  772.                     ; parity code translation table
  773. partab    db    5,3,1,4,2        ; even, mark, none, odd, space
  774. lpartab equ    $-partab
  775. parcode db    0            ; parity code (0-4)
  776.                     ; baud rate code translation table
  777. ; 45.5 - no VT100 code (call it 50),50,75,110,134.5,150,300,600,1200,
  778. ; 1800,2000,2400,4800,9600,19200,38400,57600,115200  extended beyond DEC
  779. baudtab db    0,0,8,16,24,32,48,56,64,72,80,88,104,112,120,128,128,128,64,8
  780. lbaudtab equ    $-baudtab-1    ; last two are 1200/75 for split speeds
  781. baudidx db    0            ; index into baud rate table
  782. datbits db    7            ; number of databits (7 or 8)
  783.  
  784. ttstate dw    offset atnrm        ; terminal automata state
  785. ttstateST dw    offset atnorm        ; state for action after ST seen
  786. att_normal db    07H            ; default normal screen coloring
  787. oldterm    db    0            ; terminal type from previous entry
  788. iniflgs    dw    0            ; status flags at entry time
  789. modeset db    0            ; temp for atsm/atrm
  790. anspflg    db    0            ; printer flag bits and definitions
  791. h19stat    db    0            ; H-19 extra status bits
  792. h19ctyp    db    1            ; H-19 cursor type (1=ul, 2=bk, 4=off)
  793. h19cur    dw    0            ; H-19 saved cursor position
  794. atctype    db    1            ; VTxxx cursor type (1=ul,2=bk, 4=off)
  795. insmod    db    0            ; insert mode on (1) or off (0)
  796. belcol    db    72            ; column at which to ring margin bell
  797. kbicsr    dw    0            ; cursor when keyboard input typed
  798. kbiflg    db    0            ; set/reset for keyboard input
  799. ttkbi    db    0            ; flag for keyboard input seen
  800. transflg db    0            ; flag to say TRANSLATE INPUT worked
  801. ten    dw    10            ; word 10 for multiplying
  802.  
  803. setptr    dw    0            ; hold offset of designated char set
  804. upss    db    96,'A',0,0        ; User Preferred Supplemental Set
  805.                     ; size, ident (DEC Supplemental Gr)
  806.  
  807. ; Start of save cursor material
  808. savelist equ    this byte        ; top of list of things to save
  809. cursor    dw    0            ; cursor position
  810. curattr db    07h            ; cursor attribute
  811. svattr_index    equ $-savelist        ; offset of saved cursor attribute
  812. video_state db    0            ; video state (0=normal, 1=reversed)
  813. atwrap    db    0            ; autowrap flag
  814. GLptr    dw    0            ; pointer to char set for GL
  815. GRptr    dw    0            ; pointer to char set for GR
  816. SSptr    dw    0            ; pointer to char set for single shift
  817. G0set    db    gsize+3 dup (0)        ; make G0..G3 char set space
  818. G1set    db    gsize+3 dup (0)
  819. G2set    db    gsize+3 dup (0)
  820. G3set    db    gsize+3 dup (0)
  821. lsavecu equ    $-savelist        ; length of stuff to save
  822.  
  823. savecu    db    lsavecu dup (0)        ; saved cursor, attr., charset, etc
  824. savflgs dw    0            ; saved flags for atsc/atrc
  825. ; End of save cursor material
  826.  
  827. ; tab stops, stored here
  828. tabs    db    (swidth+7)/8 dup (0)    ; active tab stops, one column per bit
  829. deftabs    db    (swidth+7)/8 dup (0)    ; default (setup) tab stops
  830.  
  831. ; byte per line, type of line: 0=normal, 1=double wide, 2=double high
  832. linetype db    slen dup (0)
  833. low_rgt    dw    0            ; text screen dimensions
  834.                     ; byte low_rgt = max column (79)
  835.                     ; byte low_rgt+1 = max row (23)
  836. oldscrn    dw    0            ; old screen. hi=rows-1, low=cols-1
  837.  
  838. ; Scrolling region - do not separate or change order of mar_top & mar_bot
  839. mar_top db    0            ; scrolling region top margin
  840. mar_bot db    23            ; scrolling region bottom margin
  841. scroll    db    1            ; lines to scroll
  842.  
  843. dspstate db    0            ; Display state (mode)line work byte
  844. dspmsave dw    0            ; saved main dsp scrolling margins
  845. dspcstat dw    0            ; saved cursor pos for status line
  846. dspcmain dw    0            ; saved cursor pos for main display
  847.  
  848. led_col equ    65            ; column position for "LEDs" display
  849. led_off equ    '.'            ; "Off" LED
  850. v320leds db    'VT320 ....'        ; VT320 mode (all 10 characters)
  851. v220leds db    'VT220 ....'        ; VT220 mode
  852. v102leds db    'VT102 ....'        ; VT102 mode
  853. v100leds db    'VT100 ....'        ; VT100 mode
  854. v52leds db    'VT52      '        ; VT52 mode
  855. h19leds    db    'Heath-19  '        ; Heath-19 mode
  856. honeyleds db    'Honey ....'        ; Honeywell VIP 7809
  857.  
  858.     even                ; Control sequence storage area
  859. dnparam    dw    0            ; number of parameters for DCS
  860. dparam    dw    maxparam dup (0)    ; Parameters for DCS
  861. dlparam    db    0            ; a single letter Parameter for DCS
  862. dninter    dw    0            ; number of DCS intermediates
  863. dinter    db    maxinter dup (0)    ; Intermediates for DCS
  864. dcsstrf    db    0            ; Final char of DCS
  865. emubufc    dw    0            ; count of chars in string buffer
  866. emubuf    db    66 dup (0)        ; emulator string storage buffer
  867.     db    0            ; safety for string overflow
  868. emubufl    dw    $-emubuf        ; length of emulator buffer
  869. data    ends
  870.  
  871. code2    segment
  872.     extrn    tekini:far, tekemu:far, tekend:far
  873. code2    ends
  874.  
  875. code    segment
  876.     extrn    prtbout:near, prtnout:near, csrtype:near, atsclr:near
  877.     extrn    vtscru:near, vtscrd:near, chgdsp:near, trnprs:near
  878.     extrn    cptchr:near, pntchr:near, pntchk:near, setpos:near
  879.     extrn    pntflsh:near, vtbell:near, vtrmac:near,vtsmac:near
  880.     extrn    getpos:near, setatch:near, getatch:near, putchar:near
  881.     extrn    revideo:near, getbold:near, setbold:near, clrbold:near
  882.     extrn    getblink:near, setblink:near, clrblink:near, getunder:near
  883.     extrn    setunder:near, clrunder:near, revscn:near, setcolor:near
  884.     extrn    clrmod:near, modlin:near, setudk:near, udkclear:near
  885.     extrn    setrev:near, clrrev:near, product:near, tekrpal:near
  886.     extrn    atparse:near, atpclr:near, atdispat:near
  887.     extrn    insdecom:near, tekinq:near, tekpal:near, dec2di:near
  888.  
  889.     assume    cs:code, ds:data, es:nothing
  890.  
  891. ; ANSI terminal output routine.     Call with character in al.
  892.  
  893. anstty    proc    near            ; ANSI terminal output
  894.     mov    dx,cursor        ; some routines need cursor in dx
  895.     mov    kbiflg,0        ; clear old flag value
  896.     test    yflags,trnctl        ; Debug mode?
  897.     jz    anstt1            ; z = no
  898.     jmp    atdeb            ; yes, just translate control chars
  899. anstt1:    cmp    ttkbi,0            ; new keyboard input?
  900.     je    anstt2            ; e = no, just continue
  901.     mov    kbiflg,1        ; yes, set flag
  902.     mov    kbicsr,dx        ; save old cursor
  903.     mov    ttkbi,0            ; clear this flag
  904.  
  905. anstt2:    test    anspflg,vtcntp        ; print controller on?
  906.     jz    anstt4            ; z = no
  907.     test    yflags,capt        ; capturing output?
  908.     jz    anstt3            ; z = no, forget this part
  909.     push    ax            ; save char
  910.     call    cptchr            ; give it captured character
  911.     pop    ax            ; restore character
  912. anstt3:    jmp    ttstate            ; print transparently
  913.  
  914. anstt4:    or    al,al            ; NUL char?
  915.     jz    atign            ; z = yes, ignore it before logging
  916.     test    yflags,capt        ; capturing output?
  917.     jz    anstt8            ; z = no, forget this part
  918.     call    cptchr            ; give it captured character
  919.                     ; Direct char to processor module
  920. anstt8:    cmp    vtemu.vtchset,12    ; ASCII (0) or NRC's (1-12) active?
  921.     ja    anstt8b            ; a = no
  922.     cmp    vtemu.vtchset,0        ; ASCII?
  923.     je    anstt8b            ; e = yes
  924.     and    al,7fh            ; yes, NRCs force chars to 7-bits
  925. anstt8b:test    al,not 9fh        ; control chars (0-1fh, 80h-9fh)?
  926.     jnz    anstt9            ; nz = no
  927.     cmp    al,20h            ; C0 control code?
  928.     jb    anstt8c            ; b = yes
  929.     cmp    vtemu.vtchset,14    ; TRANSPARENT?
  930.     je    anstt9            ; e = yes, pass all others
  931. anstt8c:jmp    atctrl            ; dispatch on control code
  932. anstt9:    jmp    ttstate            ; dispatch according to state
  933. anstty    endp
  934.  
  935. atign:    ret                ; something to be ignored
  936.  
  937. atnorm: mov    ttstate,offset atnrm    ; reset state to "normal"
  938.     mov    ttstateST,offset atnorm    ; reset state for ST seen
  939.     ret
  940.             
  941. atnrm    proc    near            ; Normal character (in AL) processor
  942.     cmp    SSptr,0            ; single shift needed?
  943.     je    atnrm10            ; e = no
  944.     and    al,not 80h        ; strip high bit
  945.     mov    bx,SSptr        ; pointer to desired char set
  946.     mov    SSptr,0            ; clear single shift indicator
  947.     jmp    short atnrm12        ; process
  948.  
  949. atnrm10:test    al,80h            ; high bit set for GRight?
  950.     jnz    atnrm11            ; nz = yes
  951.     mov    bx,GLptr        ; GL char set
  952.     jmp    short atnrm12        ; process
  953.  
  954. atnrm11:and    al,not 80h        ; strip high bit
  955.     mov    bx,GRptr        ; GR char set
  956.  
  957. atnrm12:xlatb                ; translate al to new char in al
  958. atnrm13:cmp    rxtable+256,0        ; TRANSLATION INPUT turned off?
  959.     je    atnrm14            ; e = yes, use ISO mechanisms
  960.     mov    bx,offset rxtable    ; address of translate table
  961.     mov    ah,al            ; copy char
  962.     xlatb                ; new char is in al
  963. atnrm14:cmp    al,DEL            ; ANSI Delete char?
  964.     jne    atnrm2            ; ne = no
  965.     ret                ; ignore DEL
  966.                     ; use atnrm2: for debug simple tty dsp
  967. atnrm2:    mov    dx,cursor        ; get cursor virtual position
  968.     test    vtemu.vtflgop,decawm    ; Autowrap active?
  969.     jz    atnrm2a            ; z = no
  970.     mov    cx,low_rgt        ; copy logical cursor margins to cx
  971.     push    bx
  972.     mov    bl,dh            ; get row
  973.     xor    bh,bh
  974.     cmp    linetype[bx],0        ; single width line?
  975.     pop    bx            ; pop preserves flags
  976.     je    atnrm2c            ; e = yes, single
  977.     shr    cl,1            ; halve right column # for wide chars
  978. atnrm2c:cmp    dl,cl            ; want to write beyond right margin?
  979.     jb    atnrm2a            ; b = no
  980.     cmp    atwrap,0        ; autowrap pending?
  981.     je    atnrm2a            ; e = no
  982.     test    anspflg,vtautop        ; printing desired?
  983.     jz    atnrm2a            ; e = no
  984.     push    dx
  985.     push    ax            ; save char
  986.     mov    dh,atwrap        ; get 1+last display line's row
  987.     dec    dh            ; up one line
  988.     call    pntlin            ; print line
  989.     mov    al,LF            ; terminate in LF
  990.     call    pntchr
  991.     call    pntflsh            ; flush printer buffer
  992.     pop    ax            ; recover char in AL
  993.     pop    dx
  994. atnrm2a:push    ax            ; save character
  995.     call    atscur            ; set cursor physical position
  996.     pop    ax
  997.     cmp    insmod,0        ; insert mode off?
  998.     je    atnrm3            ; e = yes
  999.     push    ax
  1000.     call    inschr            ; open a char space in this line
  1001.     push    bx
  1002.     mov    bx,cursor        ; get current row
  1003.     mov    bl,bh
  1004.     xor    bh,bh
  1005.     cmp    linetype [bx],0        ; single width line?
  1006.     je    atnrm2b            ; e = yes
  1007.     call    inschr            ; open second space for double width
  1008. atnrm2b:pop    bx
  1009.     pop    ax            ; restore char
  1010.                     ; set cursor before writing char
  1011. atnrm3:    mov    bl,dh            ; check for double characteristic
  1012.     xor    bh,bh            ; bx = row, in bl
  1013.     cmp    linetype [bx],0        ; normal characteristic?
  1014.     je    atnrm4a            ; e = yes
  1015.     shl    dl,1            ; double the column number
  1016.     push    dx
  1017.     call    direction        ; set dx to desired position
  1018.     call    setpos            ; set cursor position
  1019.     pop    dx
  1020.     mov    ah,curattr        ; current attribute
  1021.     call    setatch            ; write char (al) and attribute (ah)
  1022.     inc    dl            ; next column
  1023.     push    dx
  1024.     call    direction        ; set dx to desired position
  1025.     call    setpos            ; set cursor position
  1026.     pop    dx
  1027.     mov    al,' '            ; use a space for doubling
  1028.     mov    ah,curattr        ; current attribute
  1029.     call    setatch            ; write char (al) and attribute (ah)
  1030.     shr    dl,1            ; keep "cursor" in single units
  1031.     jmp    short atnrm4b        ; check autowrap in double width mode
  1032.  
  1033. atnrm4a:mov    ah,curattr        ; current attribute
  1034.     call    setatch            ; write char (al) and attribute (ah)
  1035.                     ; set physical cursor after this char
  1036. atnrm4b:test    vtemu.vtflgop,decawm    ; Autowrap active?
  1037.     jz    atnrm5            ; z = no
  1038.     mov    cx,low_rgt        ; copy logical cursor margins to cx
  1039.     push    bx
  1040.     mov    bl,dh            ; get row
  1041.     xor    bh,bh
  1042.     cmp    linetype[bx],0        ; single width line?
  1043.     pop    bx            ; pop preserves flags
  1044.     je    atnrm4c            ; e = yes, single
  1045.     shr    cl,1            ; halve right column # for wide chars
  1046. atnrm4c:cmp    dl,cl            ; wrote in right-most column?
  1047.     jb    atnrm5            ; b = no
  1048.     inc    dl            ; say want to use next column
  1049.     mov    atwrap,dh        ; turn on wrap flag with 1 + this row
  1050.     inc    atwrap            ;  so 0 means no wrap pending
  1051.     cmp    flags.vtflg,ttheath    ; emulating a H-19? [uci]
  1052.     je    atscur            ; e = yes, show wrap now. [uci]
  1053.     mov    cursor,dx        ; virtual cursor position
  1054.     ret                ; exit without moving cursor from eol
  1055. atnrm5:    mov    dx,cursor        ; restore cursor position
  1056.     inc    dl            ; bump cursor
  1057.     mov    atwrap,0        ; say not about to wrap
  1058.  
  1059. atscur: cmp    dl,250            ; left of column zero? (wide screen)
  1060.     jb    atscu1            ; b = no, continue
  1061.     xor    dl,dl            ; set at column zero
  1062. atscu1:    mov    cl,byte ptr low_rgt    ; copy logical margin; cl = right col
  1063.     push    bx
  1064.     mov    bl,dh            ; get row
  1065.     xor     bh,bh
  1066.     cmp    linetype [bx],0        ; single width lines?
  1067.     pop    bx
  1068.     je    atscu1a            ; e = yes, single width
  1069.     shr    cl,1            ; halve column # for double wides
  1070. atscu1a:cmp    dl,cl            ; right of right margin?
  1071.     jbe    atscu3            ; be = no, continue
  1072.     mov    dl,cl            ; assume no autowrap
  1073.     test    vtemu.vtflgop,decawm    ; Autowrap?
  1074.     jz    atscu3            ; z = no
  1075.     xor    dl,dl            ; set to column zero
  1076.     cmp    dh,byte ptr low_rgt+1    ; at bottom of screen?
  1077.     je    atscu1b            ; e = yes
  1078.     cmp    dh,mar_bot        ; at bottom of scrolling region?
  1079.     jl    atscu2            ; l = No - bump cursor and continue
  1080. atscu1b:mov    scroll,1        ; scroll count = 1 line
  1081.     call    atscru            ; scroll up
  1082.     dec    dh            ; offset inc dh below
  1083. atscu2: inc    dh            ; just bump it
  1084. atscu3: or    dh,dh            ; constrain row to valid range
  1085.     jge    atscu4            ; ge = non-negative row, ok
  1086.     xor    dh,dh
  1087. atscu4: cmp    dh,byte ptr low_rgt+1    ; 25th line?
  1088.     jle    atscu5            ; le = no
  1089.     mov    dh,byte ptr low_rgt+1    ; set to 24th line
  1090.     cmp    flags.vtflg,ttheath    ; emulating a Heath-19?
  1091.     jne    atscu4a            ; ne = no [hlk]
  1092.     test    h19stat,h19l25        ; Heath 25th line enabled?
  1093.     jz    atscu5            ; z = no
  1094. atscu4a:inc    dh            ; go to line 25 [hlk]
  1095.     test    yflags,modoff        ; is mode line off?
  1096.     jnz    atscu4b            ; nz = yes
  1097.     push    dx            ; save cursor position
  1098.     call    clrmod            ; clear the line
  1099.     or    yflags,modoff        ; now say it's off (owned by host)
  1100.     pop    dx
  1101. atscu4b:mov    flags.modflg,2        ; say mode line is owned by host
  1102.  
  1103. atscu5:    mov    cursor,dx        ; Set cursor and return
  1104.     push    dx
  1105.     mov    bl,dh            ; get row
  1106.     xor    bh,bh            ; clear high byte
  1107.     cmp    linetype [bx],0        ; single width line?
  1108.     je    atscu5a            ; e = yes
  1109.     shl    dl,1            ; double the column number
  1110. atscu5a:call    direction        ; set dx to desired position
  1111.     call    setpos            ; set cursor physical position
  1112.     pop    dx
  1113.     test    vtemu.vtflgop,vsmarginbell; do we care about margin bell?
  1114.     jz    atscu6            ; z = no, return if no margin bell
  1115.     cmp    kbiflg,0        ; is keyboard input flag set?
  1116.     je    atscu6            ; e = no, just return
  1117.     mov    bx,kbicsr        ; cursor at previous keyboard input
  1118.     cmp    bh,dh            ; same row as now?
  1119.     jne    atscu6            ; ne = no, just return
  1120.     cmp    bl,belcol        ; old cursor at or left of bell column?
  1121.     ja    atscu6            ; a = no, just return
  1122.     cmp    dl,belcol        ; new cursor past bell column?
  1123.     jbe    atscu6            ; be = no, just return
  1124.     call    vtbell            ; ring the bell
  1125. atscu6:    ret
  1126. atnrm    endp
  1127.  
  1128. ; Control-character dispatcher
  1129. atctrl:    cmp    al,escape        ; an escape sequence starting?
  1130.     je    atctrl1            ; e = yes, don't print it
  1131.     cmp    al,CSI            ; this kind of escape?
  1132.     je    atctrl1            ; e = yes
  1133.     test    anspflg,vtcntp        ; printing desired?
  1134.     jz    atctrl1            ; z = no
  1135.     call    pntchr            ; print char in al
  1136. atctrl1:xor    ah,ah            ; clear for word use below
  1137.     test    al,80h            ; high bit set?
  1138.     jnz    atctrl2            ; nz = yes
  1139.     mov    di,ax            ; use AL as a word index
  1140.     shl    di,1
  1141. atctrl3:jmp    ansc0[di]        ; dispatch on C0 control codes
  1142. atctrl2:and    al,not 80h        ; strip high bit
  1143.     mov    di,ax            ; use AL as a word index
  1144.     shl    di,1
  1145.     test    flags.vtflg,ttvt320+ttvt220 ; doing VT320/VT220?
  1146.     jz    atctrl3            ; z = no, trim back to C0
  1147. atctrl4:jmp    ansc1[di]        ; dispatch on C1 control codes
  1148.  
  1149. ; Control code routines
  1150. atbs:    or    dl,dl            ; Backspace, too far?
  1151.     jz    atbs1            ; z = at column 0 already
  1152.     dec    dl            ; backup cursor
  1153. atbs1:    call    atccpc            ; check range
  1154.     jmp    atscu5            ; set cursor and return
  1155.  
  1156. atht:    cmp    flags.vtflg,ttheath    ; Horizontal Tab, Heath-19 mode?
  1157.     je    atht2            ; e = yes, handle specially
  1158.     xor    ch,ch
  1159.     mov    cl,byte ptr low_rgt
  1160.     cmp    dl,cl            ; at or beyond last column?
  1161.     jae    atbs1            ; ae = yes check range, set cursor
  1162. atht1:    inc    dl            ; tab always moves at least one column
  1163.     push    si
  1164.     mov    si,vtemu.vttbst        ; active buffer
  1165.     call    istabs            ; returns carry set if at a tabstop
  1166.     pop    si
  1167.     jc    atht1a            ; c = at a tabstop
  1168.     loopz    atht1
  1169. atht1a:    jmp    short atbs1        ; check range, set cursor, and return
  1170.  
  1171. atht2:    mov    dx,cursor        ; Heath-19. get cursor position
  1172.     add    dl,8            ; tabs are every 8 columns
  1173.     and    dl,not 7        ; do modulo 8
  1174.     cmp    dl,byte ptr low_rgt    ; check against right edge
  1175.     jbe    atht3            ; be = in range
  1176.     mov    dl,byte ptr low_rgt    ; else go to right margin
  1177. atht3:    jmp    atscu5            ; set cursor and return
  1178.  
  1179. atlf:    test    vtemu.vtflgop,anslnm    ; Line Feed, New-line mode?
  1180.     jz    atlf2            ; z = no, just move to next line down
  1181.     xor    dl,dl            ; move to left margin also
  1182. atlf2:    test    anspflg,vtautop        ; printing desired?
  1183.     jz    atlf3            ; e = no
  1184.     push    dx
  1185.     push    ax            ; save char
  1186.     call    pntlin            ; print current line
  1187.     pop    ax            ; recover char in AL, print it too
  1188.     call    pntchr
  1189.     call    pntflsh            ; flush printer buffer
  1190.     pop    dx
  1191. atlf3:    inc    dh            ; index line down
  1192.     call    atccic            ; check indexing
  1193.     call    ax            ; call scrolling routine
  1194.     jmp    atscu5            ; set cursor
  1195.  
  1196. atcr:    xor    dl,dl            ; Carriage Return, go to left margin
  1197.     cmp    flags.vtflg,ttheath    ; Heath-19?
  1198.     jne    atcr1            ; ne = no
  1199.     test    h19stat,h19alf        ; auto line feed on?
  1200.     jnz    atlf2            ; nz = yes, do the LF part above
  1201. atcr1:    jmp    atscu5            ; set cursor and return
  1202.  
  1203. atff:    cmp    ttstate,offset atescf    ; Form Feed, parsing escape sequence?
  1204.     jne    atlf            ; ne = no, do as line feed
  1205. atff1:    test    denyflg,tekxflg        ; is auto Tek mode disabled?
  1206.     jnz    atlf            ; nz = yes, treat as line feed
  1207.     call    atsc            ; save cursor and associated data
  1208.     mov    al,escape
  1209.     call    TEKEMU
  1210.     mov    al,FF
  1211.     call    TEKEMU            ; feed to Tektronix Emulator, al=FF
  1212.     jmp    atnorm
  1213.  
  1214. atcan:    mov    parstate,0        ; CAN, clear esc seq parser
  1215.     jmp    atnorm
  1216.  
  1217. atenq:    cmp    flags.vtflg,tthoney    ; ENQ, Honeywell terminal?
  1218.     jne    atenq2            ; ne = no, ignore ENQ
  1219.     mov    ttyact,0        ; start grouping for networks
  1220.     mov    cx,ENQstrl        ; length of string
  1221.     mov    si,offset ENQstr    ; ptr to string
  1222. atenq1:    cld    
  1223.     lodsb                ; get a byte
  1224.     push    cx            ; save regs
  1225.     push    si
  1226.     call    prtbout            ; send to port WITHOUT echo
  1227.     pop     si
  1228.     pop    cx
  1229.     loop    atenq1            ; loop for all characters
  1230.     mov    ttstate, offset atnrm    ; reset to normal and return
  1231.     mov    ttyact,1        ; end group output for networks
  1232. atenq2:    ret
  1233.  
  1234. atesc:    mov    ttstate,offset atescf    ; ESC, next state is escape follower
  1235.     ret
  1236.  
  1237. ; Respond to character following Escape, dispatch on that char
  1238. atescf:    call    atpclr            ; clear parser argument list
  1239.     mov    bx,offset ansesc    ; ANSI escape table
  1240.     mov    ah,flags.vtflg
  1241.     test    ah,ttvt320+ttvt220+ttvt102+ttvt100+tthoney ; VT320 etc?
  1242.     jnz    atescf2            ; nz = yes
  1243.     mov    bx,offset v52esc    ; VT52 escape table
  1244.     cmp    ah,ttvt52        ; VT52?
  1245.     je    atescf1            ; e = yes
  1246.     mov    bx,offset h19esc    ; use Heath-19 table
  1247.     cmp    ah,ttheath        ; Heath-19?
  1248.     je    atescf1            ; e = yes
  1249.     ret                ; return on error
  1250. atescf1:mov    ttstate,offset atnrm    ; reset state to "normal"
  1251.     jmp    atdispat        ; perform dispatch via table in BX
  1252.  
  1253. atescf2:mov    bx,offset ansesc    ; ANSI escape table, for atdispat
  1254.     test    al,not (2fh)        ; in intermediates (column 2)?
  1255.     jnz    atescf1            ; nz = no, dispatch on this char
  1256.     mov    ttstate,offset atescf2    ; stay in this state til col 3 or more
  1257.     mov    bx,ninter        ; number of intermediates
  1258.     cmp    bx,maxinter        ; done enough already?
  1259.     jae    atescf3            ; ae = yes, ignore the excess
  1260.     mov    inter[bx],al        ; store this one
  1261.     inc    ninter            ; one more
  1262. atescf3:ret                ; get more input
  1263.  
  1264.                     ; CSI, char 9bh (ANSI CSI == ESC [)
  1265. atcsi0:    cmp    ninter,0        ; any intermediates from ESC..[?
  1266.     je    atcsi            ; e = no, else not this item
  1267.     jmp    atnorm            ; reset state to "normal"
  1268.                     ; enter here with real CSI char
  1269. atcsi:    mov    ttstate,offset atparse    ; next state is parse control seq
  1270.     mov    pardone,offset atcsi1    ; where to jmp when done
  1271.     mov    parfail,offset atnorm    ; where to jmp if failure
  1272.     jmp    atpclr            ; clear parser parameters and return
  1273.  
  1274. atcsi1:    mov    bx,offset anstab    ; ANSI Final character table
  1275.     mov    ttstate,offset atnrm    ; reset state to "normal"
  1276.     jmp    atdispat        ; dispatch on character
  1277.  
  1278. h19csi:    test    vtemu.vtflgop,decanm    ; Heath-19 "ESC [", is ANSI mode on?
  1279.     jnz    h19csi1            ; nz = yes
  1280.     mov    ttstate,offset atnrm    ; else ignore the "[" (kbd lock)
  1281.     ret
  1282. h19csi1:mov    ttstate,offset atparse    ; H-19, ESC [ parser
  1283.     mov    pardone,offset h19csi2     ; where to jmp when done
  1284.     mov    parfail,offset atnorm    ; where to jmp if failure
  1285.     ret                ; get next char
  1286. h19csi2:mov    bx,offset h19ans    ; H-19 ANSI Final character table
  1287.     mov    ttstate,offset atnrm    ; reset state to "normal"
  1288.     jmp    atdispat        ; dispatch on character
  1289.  
  1290. ; Process Device Control Strings (DCS or ESC P lead-in chars, already read).
  1291. atdcs0:    cmp    ninter,0        ; any intermediates?
  1292.     je    atdcs            ; e = no, else not this item
  1293.     jmp    atnorm            ; reset state to normal
  1294.                     ; enter here with real DCS char
  1295. atdcs:    mov    ttstate,offset atparse    ; next state is parse control seq
  1296.     mov    pardone,offset atdcs1    ; where to jmp when done
  1297.     mov    parfail,offset atnorm    ; where to jmp if failure
  1298.     ret
  1299. atdcs1:    mov    dcsstrf,al        ; record Final char
  1300.     mov    emubufc,0        ; clear string count
  1301.     mov    cx,maxparam        ; number of DCS parameters
  1302.     push    si            ; copy these to the DCS area so that
  1303.     push    di            ;  they are not lost when an ST is
  1304.     push    es            ;  parsed (parser clears ESC items)
  1305.     push    ds
  1306.     pop    es
  1307.     mov    si,offset param        ; ESC paramater storage area, numeric
  1308.     mov    di,offset dparam    ; DCS parameter storage area, numeric
  1309.     cld
  1310.     rep    movsw            ; copy set to DCS storage area
  1311.     mov    cl,lparam         ; copy letter Paramter
  1312.     mov    dlparam,cl
  1313.     mov    cx,maxinter        ; number of intermediate characters
  1314.     mov    si,offset inter        ; source
  1315.     mov    di,offset dinter    ; destination
  1316.     rep    movsb
  1317.     mov    si,nparam        ; number of parameters
  1318.     mov    dnparam,si
  1319.     mov    si,ninter
  1320.     mov    dninter,si        ; number of intermediates
  1321.     pop    es
  1322.     pop    di
  1323.     pop    si
  1324.     mov    ttstateST,offset atnorm ; default ST completion state
  1325.     mov    emubufc,0        ; clear processed string length
  1326.     mov    al,dcsstrf        ; get DCS Final char
  1327.     mov    bx,offset dcstab    ; DCS dispatch table
  1328.     call    atdispat        ; go to DCS handler
  1329.     ret
  1330.  
  1331. ; Process ST or ESC \  String Terminator.
  1332. atgotst0:cmp    ninter,0        ; any intermediates in ESC..\?
  1333.     je    atgotst            ; e = no, else not this item
  1334.     jmp    atnorm            ; reset state to normal
  1335.                     ; enter here with real ST char
  1336. atgotst:jmp    ttstateST        ; go to state for ST arrival
  1337.  
  1338. ; Read and discard OSC (ESC ]), PM (ESC ^), APC (ESC _) control sequences
  1339. ; through final ST (ESC \) terminator.
  1340. atdcsnul0:cmp    ninter,0        ; any intermediates in ESC..\?
  1341.     je    atdcsnul        ; e = no, else not this item
  1342.     ret
  1343.                     ; enter here with real ST char
  1344. atdcsnul:mov    dcsstrf,0        ; simulate a null (dummy) Final char
  1345.     mov    emubufc,0        ; clear string count
  1346.     mov    ttstate,offset atdcsnul    ; keep coming here
  1347.     mov    ttstateST,offset atnorm    ; where to go when ST has been seen
  1348.     ret                ; consume chars
  1349.  
  1350. ; User Definable Key processor of DCS strings.
  1351. atudk:    cmp    dinter,0        ; no intermediates?
  1352.     je    atudk1            ; e = correct
  1353.     mov    ninter,0        ; setup atdcsnul for proper form
  1354.     jmp    short atdcsnul        ; bad, consume the rest
  1355.  
  1356. atudk1:    cmp    dparam,1        ; is initial Parameter Pc a 1?
  1357.     jae    atudk2            ; ae = yes, clear only this key
  1358.     call    udkclear        ; clear all UDKeys
  1359.     mov    dparam,1        ; and turn off Parameter
  1360. atudk2:    mov    ttstate,offset atudk3    ; next state is get a substring
  1361.     mov    ttstateST, offset atudk6 ; for when ST has been seen
  1362.     ret
  1363.  
  1364. atudk3:    cmp    al,';'            ; string separator?
  1365.     je    atudk5            ; e = yes, process string to-date
  1366.     mov    bx,emubufc        ; count of chars in string buffer
  1367.     cmp    bx,emubufl        ; too many?
  1368.     jae    atudk4            ; ae = too many, ignore extras
  1369.     mov    emubuf[bx],al        ; store the char
  1370.     inc    emubufc            ; count it
  1371. atudk4:    ret
  1372. atudk5:    mov    si,offset emubuf    ; address of string buffer is DS:SI
  1373.     mov    cx,emubufc        ; count of buffer contents
  1374.     call    setudk            ; insert string definition
  1375.     mov    emubufc,0        ; clear string buffer
  1376.     ret
  1377. atudk6:    call    atudk5            ; ST seen, process last string
  1378.     jmp    atnorm            ; reset state to normal
  1379.  
  1380. ; Call this routine to deliver Parameters in succession. Each call points to
  1381. ; a Parameter as param[si], where si is maintained here. If there are no
  1382. ; Parameters the effect is the same as one Parameter with a value of zero.
  1383. ; Enter with di = offset of action routine to be called for each Parameter.
  1384. ; cx, si, and di are preserved over the call to the action routine.
  1385.  
  1386. atreps    proc    near
  1387.     xor    si,si            ; initialize parm index
  1388.     mov    cx,nparam        ; number of Parameters
  1389.     or    cx,cx            ; zero?
  1390.     jnz    atrep1            ; nz = no
  1391.     inc    cx            ; zero parms is same as 1
  1392. atrep1: push    cx            ; save loop counter
  1393.     push    si            ; save parameter index
  1394.     push    di            ; save call vector
  1395.     call    DI            ; call indicated routine
  1396.     pop    di            ; restore registers
  1397.     pop    si
  1398.     pop    cx
  1399.     add    si,2            ; advance to next parameter
  1400.     loop    atrep1            ; loop for all
  1401.     ret
  1402. atreps    endp
  1403.  
  1404.                     ; Action routines
  1405. atind0:    cmp    ninter,0        ; any intermediates?
  1406.     je    atind            ; e = no, else not this item
  1407.     ret
  1408. atind:    inc    dh            ; IND (index), move cursor down one
  1409. atind1: call    atccic            ; check cursor position
  1410.     call    ax            ; scroll if necessary
  1411.     jmp    atscu5            ; set cursor, etc. and return
  1412.  
  1413. atnel0:    cmp    ninter,0        ; any intermediates from ESC..E?
  1414.     je    atnel            ; e = no, else not this item
  1415.     jmp    atdgnrc            ; try Nowegian/Danish NRC designator
  1416.                     ; enter here with real NEL char
  1417. atnel:    xor    dl,dl            ; NEL, next line - sort of like CRLF
  1418.     inc    dh            ; ... all in one command
  1419.     jmp    short atind1        ; check cursor, etc., and return
  1420.  
  1421. atri0:    cmp    ninter,0        ; any intermediates?
  1422.     je    atri            ; e = no, else not this item
  1423.     ret
  1424. atri:    cmp    flags.vtflg,ttheath    ; Heath-19?
  1425.     jne    atri1            ; ne = no
  1426.     cmp    dh,byte ptr low_rgt+1    ; on 25th line?
  1427.     jbe    atri1            ; be = no
  1428.     ret                ; no vertical for Heath on 25th line
  1429. atri1:    dec    dh            ; RI, reverse index
  1430.     jmp    short atind1        ; check cursor, etc., and return
  1431.  
  1432.                     ; HTS, horizontal tab set in this col
  1433. athts0:    cmp    ninter,0        ; any intermediates from ESC..H?
  1434.     je    athts            ; e = no, else not this item
  1435.     jmp    atdgnrc            ; try Swedish NRC designator
  1436. athts:    call    atccpc            ; make column number valid
  1437.     mov    si,vtemu.vttbst        ; active buffer
  1438.     jmp    tabset            ; say set tab in this column (DL)
  1439.  
  1440.                     ; DECSC
  1441. atsc:    mov    si,offset savelist    ; save cursor, attribute, char set etc
  1442.     mov    di,offset savecu    ; place to save the stuff
  1443.     mov    cx,lsavecu        ; length of save area
  1444.     push    es            ; save es
  1445.     push    ds
  1446.     pop    es            ; set es to data segment
  1447.     cld
  1448.     shr    cx,1            ; divide by two for word moves
  1449.     jnc    atsc1            ; nc = even number of bytes
  1450.     movsb                ; do the odd byte
  1451. atsc1:    rep    movsw            ; save it
  1452.     pop    es
  1453.     mov    cx,vtemu.vtflgop    ; save a copy of the flags
  1454.     mov    savflgs,cx
  1455.     ret
  1456.                     ; DECRC
  1457. atrc:    mov    si,offset savecu    ; restore cursor, attributes, etc
  1458.     mov    di,offset savelist    ; where stuff goes
  1459.     mov    cx,lsavecu        ; length of save area
  1460.     push    es            ; save es
  1461.     push    ds
  1462.     pop    es            ; set es to data segment
  1463.     cld
  1464.     shr    cx,1            ; divide by two for word moves
  1465.     jnc    atrc1            ; nc = even number of bytes
  1466.     movsb                ; do the odd byte
  1467. atrc1:    rep    movsw            ; put the stuff back
  1468.     pop    es
  1469.     mov    ax,savflgs        ; get saved flags
  1470.     xor    ax,vtemu.vtflgop    ; exclusive-or with current flags
  1471.     test    ax,vsscreen        ; did screen mode change?
  1472.     jz    atrc3            ; z = no, reset saved flags and leave
  1473.     mov    ah,curattr        ; get cursor attribute that was saved
  1474.     call    revideo            ; get reversed video attributes (AH)
  1475.     mov    curattr,ah        ; store
  1476. atrc3:    mov    ax,vtemu.vtflgop    ; reset flags in case called again
  1477.     and    ax, not(decckm+deckpam+decom)  ; remove old bits [dlk]
  1478.     and    savflgs,(decckm+deckpam+decom) ; remove all but new bits [dlk]
  1479.     or    ax,savflgs        ; restore saved bits [dlk]
  1480.     mov    vtemu.vtflgop,ax    ; update these flags [dlk]
  1481.     mov    savflgs,ax
  1482.     mov    dx,cursor        ; get cursor
  1483.     mov    kbiflg,0        ; don't bother them with beeps here
  1484.     jmp    atscu5            ; set cursor
  1485.  
  1486. atkpam:    cmp    ninter,0        ; any intermediates?
  1487.     jne    atkpam1            ; ne = yes, not this item
  1488.     or    vtemu.vtflgop,deckpam    ; turn on keypad applications mode
  1489.     ret
  1490. atkpam1:jmp    atdgnrc            ; try Swiss NRC designator
  1491.  
  1492. atkpnm: and    vtemu.vtflgop,not deckpam ; turn off keypad applications mode
  1493.     ret
  1494.  
  1495.                     ; Privileged sequence, ignore it
  1496. atpriv:    cmp    ninter,0        ; any intermediates?
  1497.     jne    atpriv1            ; ne = yes, not this item
  1498.     mov    ttstate,offset atnorm    ; ignore next char
  1499. atpriv1:ret                ; and return to normal afterward
  1500.  
  1501. ; ISO 2022 three byte Announcer Summary    <ESC> <space> <final char>
  1502. ;Esc Sequence  7-Bit Environment          8-Bit Environment
  1503. ;----------    ------------------------   ----------------------------------
  1504. ;<ESC><SP>A    G0->GL                     G0->GL
  1505. ;<ESC><SP>B    G0-(SI)->GL, G1-(SO)->GL   G0-(LS0)->GL, G1-(LS1)->GL
  1506. ;<ESC><SP>C    (not used)                 G0->GL, G1->GR
  1507. ;<ESC><SP>D    G0-(SI)->GL, G1-(SO)->GL   G0->GL, G1->GR
  1508. ;<ESC><SP>E    Full preservation of shift functions in 7 & 8 bit environments
  1509. ;<ESC><SP>F    C1 represented as <ESC>F   C1 represented as <ESC>F
  1510. ;<ESC><SP>G    C1 represented as <ESC>F   C1 represented as 8-bit quantity
  1511. ;<ESC><SP>H    All graphic character sets have 94 characters
  1512. ;<ESC><SP>I    All graphic character sets have 94 or 96 characters
  1513. ;<ESC><SP>J    In a 7 or 8 bit environment, a 7 bit code is used
  1514. ;<ESC><SP>K    In an 8 bit environment, an 8 bit code is used
  1515. ;<ESC><SP>L    Level 1 of ISO 4873 is used
  1516. ;<ESC><SP>M    Level 2 of ISO 4873 is used
  1517. ;<ESC><SP>N    Level 3 of ISO 4873 is used
  1518. ;<ESC><SP>P    G0 is used in addition to any other sets:
  1519. ;              G0 -(SI)-> GL              G0 -(LS0)-> GL
  1520. ;<ESC><SP>R    G1 is used in addition to any other sets:
  1521. ;              G1 -(SO)-> GL              G1 -(LS1)-> GL
  1522. ;<ESC><SP>S    G1 is used in addition to any other sets:
  1523. ;              G1 -(SO)-> GL              G1 -(LS1R)-> GR
  1524. ;<ESC><SP>T    G2 is used in addition to any other sets:
  1525. ;              G2 -(LS2)-> GL             G2 -(LS2)-> GL
  1526. ;<ESC><SP>U    G2 is used in addition to any other sets:
  1527. ;              G2 -(LS2)-> GL             G2 -(LS2R)-> GR
  1528. ;<ESC><SP>V    G3 is used in addition to any other sets:
  1529. ;              G3 -(LS2)-> GL             G3 -(LS3)-> GL
  1530. ;<ESC><SP>W    G3 is used in addition to any other sets:
  1531. ;              G3 -(LS2)-> GL             G3 -(LS3R)-> GR
  1532. ;<ESC><SP>Z    G2 is used in addition to any other sets:
  1533. ;              SS2 invokes a single character from G2
  1534. ;<ESC><SP>[    G3 is used in addition to any other sets:
  1535. ;              SS3 invokes a single character from G3
  1536. ;
  1537. ; ISO Escape Sequences for Alphabet Designation ("F" = Final char)
  1538. ; Sequence     Function                                         Invoked By
  1539. ;  <ESC>(F     assigns 94-character graphics set "F" to G0.     SI  or LS0
  1540. ;  <ESC>)F     assigns 94-character graphics set "F" to G1.     SO  or LS1
  1541. ;  <ESC>*F     assigns 94-character graphics set "F" to G2.     SS2 or LS2
  1542. ;  <ESC>+F     assigns 94-character graphics set "F" to G3.     SS3 or LS3
  1543. ;  <ESC>-F     assigns 96-character graphics set "F" to G1.     SO  or LS1
  1544. ;  <ESC>.F     assigns 96-character graphics set "F" to G2.     SS2 or LS2
  1545. ;  <ESC>/F     assigns 96-character graphics set "F" to G3.     SS3 or LS3
  1546. ;  <ESC>$(F    assigns multibyte character set "F" to G0.       SI  or LS0
  1547. ;  <ESC>$)F    assigns multibyte character set "F" to G1.       SO  or LS1
  1548. ;  <ESC>$*F    assigns multibyte character set "F" to G2.       SS2 or LS2
  1549. ;  <ESC>$+F    assigns multibyte character set "F" to G3.       SS3 or LS3
  1550. ;     
  1551. ; Designate character sets, AL has final character, inter has all preceeding.
  1552.  
  1553. atdgfA:    call    atdgset            ; 'A' ISO Latin-1, UK-ASCII
  1554.     jc    atdgfA1            ; c = no matching pointer
  1555.     cmp    inter,'+'        ; in the 94 byte set?
  1556.     ja    atdgfA2            ; a = no
  1557.     mov    al,flags.vtflg        ; terminal type
  1558.     test    al,ttvt102+ttvt100+tthoney ; VT102, VT100 or Honeywell?
  1559.     jz    atdgfA1            ; z = no
  1560.     call    chrinit            ; UK-ASCII
  1561.     mov    di,setptr        ; get set pointer
  1562.     mov    byte ptr[di+23h],156    ; replace sharp 2/3 with Sterling sign
  1563.     mov    byte ptr[di+gsize],94    ; say this is a 94 byte set
  1564.     mov    word ptr[di+gsize+1],0+'A' ; set ident code
  1565. atdgfA1:ret
  1566. atdgfA2:call    latin1            ; set si to Latin-1 table offset
  1567.     jmp    cpyset
  1568. atdgfA3:jmp    atdgnrc            ; try British NRC
  1569.  
  1570. atdgfB:    call    atdgset            ; 'B' ASCII, get setptr from inter
  1571.     jc    atdgfA1            ; c = no matching pointer
  1572.     cmp    inter,'+'        ; in the 94 byte set?
  1573.     ja    atdgfA1            ; a = no, ignore
  1574.     jmp    chrinit            ; init the set to ASCII
  1575.  
  1576. atdgf0:    call    atdgset            ; '0', '2', DEC Special Graphics
  1577.     jc    atdgfA1            ; c = no matching pointer
  1578.     cmp    inter,'+'        ; in the 94 byte set?
  1579.     ja    atdgfA1            ; a = no, ignore
  1580. atdg52:    call    chrinit            ; init set to ASCII
  1581.     push    si
  1582.     push    di
  1583.     push    es
  1584.     push    ds
  1585.     pop    es            ; point es at data segment
  1586.     mov    di,setptr        ; address of char set table
  1587.     add    di,95            ; replace chars 95-126, skip controls
  1588.     mov    si,offset sgrtab    ; special graphics table
  1589.     mov    cx,sgrtabl        ; table length
  1590.     cmp    flags.vtflg,ttheath    ; Heath-19 rather than VT52?
  1591.     jne    atdgf53            ; ne = no, not a Heath
  1592.     mov    si,offset hgrtab    ; use Heath-19 table
  1593.     mov    cx,hgrtabl
  1594.     dec    di            ; replace chars 94-126
  1595. atdgf53:cld
  1596.     rep    movsb            ; replace chars with <s|h>grtab items
  1597.     mov    di,setptr
  1598.     mov    byte ptr[di+gsize],94    ; say this is a 94 byte set
  1599.     mov    word ptr[di+gsize+1],0+'0' ; set ident code
  1600.     pop    es
  1601.     pop    di
  1602.     pop    si
  1603.     ret
  1604.  
  1605. atdgf1:    call    atdgset            ; '1' ALT-ROM
  1606.     jc    atdgf1b            ; c = no matching pointer
  1607.     call    chrinit            ; init set to ASCII
  1608.     push    si
  1609.     push    di
  1610.     push    es
  1611.     push    ds
  1612.     pop    es            ; point es at data segment
  1613.     mov    di,setptr
  1614.     add    di,60h            ; replace a..z with 20h + (a..z)
  1615.     mov    si,di            ; special graphics table
  1616.     mov    cx,27            ; number of chars to do (a..z)
  1617.     cld
  1618. atdgf1a:lodsb                ; get a char
  1619.     add    al,20h            ; map up by 20h
  1620.     stosb
  1621.     loop    atdgf1a
  1622.     mov    di,setptr
  1623.     mov    byte ptr[di+gsize],96    ; say this is a 96 byte set
  1624.     mov    word ptr[di+gsize+1],0+'1' ; set ident code
  1625.     pop    es
  1626.     pop    di
  1627.     pop    si
  1628.     ret
  1629.  
  1630. atdgf1b:cmp    ninter,0        ; ESC 1? (Special enter Tek mode)
  1631.     jne    atdgf1c            ; ne = some, not ESC 1
  1632.     cmp    nparam,0
  1633.     jne    atdgf1c            ; ne = some, not ESC 1
  1634.     jmp    atff1            ; treat the same as ESC ^L
  1635. atdgf1c:ret
  1636.  
  1637. atdgft:    call    atdgset            ; '>' Dec Technical Set
  1638.     jc    atdgft1            ; c = no matching pointer
  1639.     cmp    inter,'+'        ; in the 94 byte set?
  1640.     ja    atdgft1            ; a = no
  1641.     mov    si,offset dectech    ; source data
  1642.     jmp    cpyset            ; copy the set
  1643. atdgft1:cmp    ninter,0        ; ESC >  set numeric keypad?
  1644.     jne    atdgft2            ; ne = no
  1645.     and    vtemu.vtflgop,not deckpam ; turn off application keypad bit
  1646. atdgft2:ret
  1647.                     ; '<' User Preferred Supplemental Set
  1648. atdgfu:    call    atdgset            ; get set pointer
  1649.     jc    atdgfu3            ; c = no matching pointer
  1650.     cmp    inter,','        ; designating the 96 char set?
  1651.     jb    atdgfu1            ; b = no, want 94
  1652.     call    latin1            ; set si to Latin-1 table offset
  1653.     cmp    word ptr upss+1,0+'A'    ; is ISO Latin-1 the preferred set?
  1654.     je    atdgfu2            ; e = yes, set it up
  1655.     ret                ; else do nothing
  1656. atdgfu1:call    decsupg            ; SI=source data is DEC Supplement Gr.
  1657.     cmp    word ptr upss+1,'5%'    ; DEC Supplemental Graphics?
  1658.     jne    atdgfu3            ; ne = no
  1659. atdgfu2:jmp    cpyset            ; copy the set
  1660. atdgfu3:ret
  1661.  
  1662. atdgfq:    call    atdgset            ; '?' Transparent
  1663.     jc    atdgfu3            ; c = no matching pointer
  1664.     call    chrinit            ; init set to ASCII
  1665.     push    si
  1666.     push    di
  1667.     push    es
  1668.     push    ds
  1669.     pop    es            ; point es at data segment
  1670.     mov    di,setptr        ; point at character set
  1671.     mov    si,di            ; 
  1672.     mov    cx,gsize        ; number of chars to do, 128
  1673.     cld
  1674. atdgfq1:lodsb                ; get a char
  1675.     add    al,80h            ; map up by 80h
  1676.     stosb
  1677.     loop    atdgfq1
  1678.     mov    di,setptr
  1679.     mov    byte ptr[di+gsize],96    ; say this is a 96 byte set
  1680.     mov    word ptr[di+gsize+1],0+'?' ; set ident code
  1681.     pop    es
  1682.     pop    di
  1683.     pop    si
  1684.     ret
  1685.  
  1686.                     ; ESC <...> <1-8>  series
  1687. atsdhl:    cmp    ninter,1        ; just one intermediate?
  1688.     jne    atsdh0            ; ne = no
  1689.     cmp    inter,'#'        ; this intermediate?
  1690.     jne    atdgnrc            ; ne = no, try NRC char set designator
  1691.     cmp    al,'3'            ; Double high lines. Top half?
  1692.     je    atsdh2            ; e = yes
  1693.     cmp    al,'4'            ; bottom half?
  1694.     je    atsdh2            ; e = yes
  1695.     cmp    al,'5'            ; restore line to single width?
  1696.     je    atsdh1            ; e = yes
  1697.     cmp    al,'6'            ; double width single height?
  1698.     je    atsdh2            ; e = yes
  1699.     cmp    al,'8'            ; screen alignment?
  1700.     je    atsdh8            ; e = yes
  1701. atsdhx:    ret                ; else ignore
  1702.  
  1703. atsdh1:    jmp    linesgl            ; set line to single width
  1704. atsdh2:    jmp    linedbl            ; expand the line to double width
  1705. atsdh8:    jmp    atalign            ; do screen alignment
  1706.  
  1707. atsdh0:    cmp    ninter,0        ; zero intermediates?
  1708.     jne    atdgf5            ; ne = no, try for more
  1709.     cmp    al,'7'            ; save cursor?
  1710.     jne    atsdh0a            ; ne = no
  1711.     jmp    atsc            ; do save cursor, ESC 7
  1712. atsdh0a:cmp    al,'8'            ; restore cursor?
  1713.     jne    atsdh0b            ; ne = no
  1714.     jmp    atrc            ; do restore cursor, ESC 8
  1715. atsdh0b:ret
  1716.  
  1717. atdgf5:    cmp    ninter,2        ; two intermediates?
  1718.     jne    atdgf5a            ; ne = no, ignore remainder
  1719.     cmp    al,'6'            ; '%6' NRC designator?
  1720.     je    atdgnrc            ; e = yes, do that above
  1721.     cmp    al,'5'            ; '%5' DEC Supplemental Graphic?
  1722.     jne    atdgf5a            ; ne = no
  1723.     cmp    inter,'+'        ; in the 94 byte set?
  1724.     ja    atdgf5a            ; a = no, ignore
  1725.     cmp    inter[1],'%'        ; '%5'?
  1726.     jne    atdgf5a            ; ne = no
  1727.     mov    ninter,1        ; help atdgset find our set
  1728.     call    atdgset            ; get set pointer
  1729.     jc    atdgf5a            ; c = no matching pointer
  1730.     call    decsupg            ; SI = source data
  1731.     jmp    cpyset            ; copy the set
  1732. atdgf5a:ret
  1733.  
  1734. ; Enter with Final esc char in al, others in array inter. Setup Gn if success.
  1735. atdgnrc    proc    near            ; check for NRC set designator
  1736.     cmp    ninter,0        ; ESC Z?
  1737.     jne    atdgnr1            ; ne = no
  1738.     jmp    atda            ; process ident request
  1739. atdgnr1:cmp    inter,'+'        ; in the 94 byte set?
  1740.     ja    atdgnrx            ; a = no, ignore
  1741.     call    findctry        ; find NRC country number in CX
  1742.     jc    atdgnrx            ; c = not found, ignore
  1743.     mov    ninter,1        ; help atdgset find our set
  1744.     call    atdgset            ; check for Gn designator
  1745.     jc    atdgnrx            ; c = not found
  1746.     jmp    setnrc5            ; setup NRC with setptr from atdgset
  1747. atdgnrx:ret                ; ignore
  1748. atdgnrc    endp
  1749.  
  1750. ; Find NRC country number, putting it into CX, given Final char in AL and
  1751. ; intermediates in array inter. Return carry set if not found.
  1752. findctry proc    near
  1753.     cmp    ninter,2        ; second intermediate (%)?
  1754.     jb    findct1            ; b = no
  1755.     ja    findct3            ; a = three or more, no match
  1756.     mov    ah,inter+1        ; get NRC intermediate
  1757.     cmp    ax,'%6'            ; Portugese NRC?
  1758.     jne    findct3            ; ne = no, fail
  1759.     mov    cx,9            ; Portuguese NRC is number 9
  1760.     clc
  1761.     ret
  1762. findct1:cmp    ninter,0        ; no intermediate?
  1763.     je    findct3            ; e = yes, no designator, fail
  1764.     mov    cx,nrcflen        ; number of NRC letters to consider
  1765.     cld
  1766.     push    di            ; save regs
  1767.     push    es
  1768.     push    ds
  1769.     pop    es
  1770.     mov    di,offset nrcfinal    ; list of NRC final chars
  1771.     repne    scasb            ; look for a match
  1772.     pop    es            ; recover reg
  1773.     jne    findct2            ; ne = failed
  1774.     dec    di            ; compenstate for auto-inc
  1775.     sub    di,offset nrcfinal    ; get distance covered
  1776.     mov    cl,nrcnum[di]        ; country number from parallel list
  1777.     xor    ch,ch            ; return number in CX
  1778.     pop    di
  1779.     clc                ; success
  1780.     ret
  1781. findct2:pop    di            ; carry set = failure
  1782. findct3:stc
  1783.     ret
  1784. findctry endp
  1785.                           ; worker for atdgf routines
  1786. atdgset:cmp    ninter,2        ; too many intermediates?
  1787.     ja    atdgsex            ; a = yes, ignore
  1788.     cmp    inter,'('        ; 94 char sets, designate G0?
  1789.     je    atdgse0            ; e = yes
  1790.     cmp    inter,')'        ; G1?
  1791.     je    atdgse1
  1792.     test    flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
  1793.     jz    atdgsex            ; z = no, G2 & G3 fixed for VT102
  1794. atdgset1:cmp    inter,'*'        ; G2?
  1795.     je    atdgse2
  1796.     cmp    inter,'+'        ; G3?
  1797.     je    atdgse3
  1798.     cmp    inter,'-'        ; 96 char sets, designate G1?
  1799.     je    atdgse1
  1800.     cmp    inter,'.'        ; G2?
  1801.     je    atdgse2
  1802.     cmp    inter,'/'        ; G3?
  1803.     je    atdgse3
  1804. atdgsex:stc                ; carry set for failure
  1805.     ret
  1806. atdgse0:mov    setptr,offset G0set    ; designate G0 set
  1807.     clc
  1808.     ret
  1809. atdgse1:mov    setptr,offset G1set    ; designate G1 set
  1810.     clc
  1811.     ret
  1812. atdgse2:mov    setptr,offset G2set    ; designate G2 set
  1813.     clc
  1814.     ret
  1815. atdgse3:mov    setptr,offset G3set    ; designate G3 set
  1816.     clc
  1817.     ret
  1818.                     ; S7C1T/S8C1T select 7/8-bit controls
  1819. ats7c:    test    flags.vtflg,ttvt320+ttvt220 ; in VT320/VT220 mode?
  1820.     jz    atdgsex            ; z = no, ignore command
  1821.     cmp    ninter,1        ; one intermediate?
  1822.     jne    ats7ca            ; ne = no
  1823.     cmp    inter,' '        ; proper intermediate?
  1824.     jne    ats7ca            ; ne = no
  1825.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls bit
  1826. ats7ca:ret                ; done
  1827.  
  1828. ats8c:    cmp    inter,' '        ; proper intermediate?
  1829.     jne    ats8ca            ; ne = no
  1830.     cmp    ninter,1        ; just one?
  1831.     jne    ats8ca            ; ne = no
  1832.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls bit
  1833. ats8ca:    ret
  1834.  
  1835. ; Designate User Preferred Supplemental Set as
  1836. ;  'A' ISO Latin-1  or  '%5' DEC Supplemental Graphics
  1837. ; Store the selection letters in array upss for later use by ESC <char> '<'
  1838. atupss:    cmp    word ptr dinter,0+'!'    ; "!u" proper intermediate?
  1839.     je    atupss0            ; e = yes
  1840.     mov    ninter,0        ; set up atdcsnul for proper form
  1841.     jmp    atdcsnul        ; consume unknown command
  1842. atupss0:mov    ah,94            ; assume 94 byte set
  1843.     cmp    dparam,1        ; 96 byte char size indicator?
  1844.     jb    atupss1            ; b = no, 94
  1845.     ja    atupss2            ; a = illegal Parameter
  1846.     mov    ah,96            ; say 96
  1847. atupss1:mov    upss,ah            ; store char set size
  1848.     mov    ttstateST,offset atupss4; where to go when ST has been seen
  1849.     mov    emubufc,0        ; clear buffer count
  1850.     mov    ttstate,offset atupss2    ; next state is get string
  1851.     ret
  1852. atupss2:mov    bx,emubufc        ; count of chars in string buffer
  1853.     cmp    bx,emubufl        ; too many?
  1854.     jae    atupss3            ; ae = too many, ignore extras
  1855.     mov    emubuf[bx],al        ; store the char
  1856.     inc    emubufc            ; count it
  1857. atupss3:ret
  1858. atupss4:mov    si,emubufc        ; count of chars in string
  1859.     mov    emubuf[si],0        ; terminate string in null
  1860.     mov    ax,word ptr emubuf    ; copy two chars from string to
  1861.     mov    word ptr upss+1,ax    ;  upss char set ident storage area
  1862.     mov    emubufc,0        ; clear the string count
  1863.     ret
  1864.  
  1865. ; Select/map character sets
  1866. atls0:    mov    GLptr,offset G0set    ; LS0,  map G0 char set into GLeft
  1867.     ret                ; Control-O
  1868. atls1:    mov    GLptr,offset G1set    ; LS1,  map G1 char set into GLeft
  1869.     ret                ; Control-N
  1870. atls1r:    cmp    ninter,0        ; any intermediate chars?
  1871.     jne    atlsx            ; ne = yes, not a Locking Shift
  1872.     mov    GRptr,offset G1set    ; LS1R, map G1 char set into GRight
  1873.     ret
  1874. atss2:    cmp    ninter,0        ; any intermediate chars?
  1875.     jne    atlsx            ; ne = yes, not a Single Shift
  1876.     mov    SSptr,offset G2set    ; SS2,  use G2 for next graphics only
  1877.     ret
  1878. atls2:    cmp    ninter,0        ; any intermediate chars?
  1879.     jne    atlsx            ; ne = yes, not a Locking Shift
  1880.     mov    GLptr,offset G2set    ; LS2,  map G2 char set into GLeft
  1881.     ret
  1882. atls2r:    cmp    ninter,0        ; any intermediate chars?
  1883.     jne    atlsx            ; ne = yes, not a Locking Shift
  1884.     mov    GRptr,offset G2set    ; LS2R, map G2 char set into GRight
  1885.     ret
  1886. atss3:    cmp    ninter,0        ; any intermediate chars?
  1887.     jne    atlsx            ; ne = yes, not a Single Shift
  1888.     mov    SSptr,offset G3set    ; SS3,  use G3 for next graphics only
  1889.     ret
  1890. atls3:    cmp    ninter,0        ; any intermediate chars?
  1891.     jne    atlsx            ; ne = yes, not a Locking Shift
  1892.     mov    GLptr,offset G3set    ; LS3,  map G3 char set into GLeft
  1893.     ret
  1894. atls3r:    cmp    ninter,0        ; any intermediate chars?
  1895.     jne    atlsx            ; ne = yes, not a Locking Shift
  1896.     mov    GRptr,offset G3set    ; LS3R, map G3 char set into GRight
  1897. atlsx:    ret
  1898.  
  1899. ; Initialize a char set to ASCII values 0..127 and ident of 94/B
  1900. ; Enter with setptr holding offset of G0set, G1set, G2set, or G3set char set
  1901. chrinit    proc    near
  1902.     push    ax
  1903.     push    cx
  1904.     push    di
  1905.     push    es
  1906.     mov    di,setptr        ; char set to init (G0..G3)
  1907.     mov    cx,gsize        ; number of bytes to do
  1908.     xor    al,al            ; initial value
  1909.     push    ds
  1910.     pop    es            ; set es to data segment
  1911.     cld
  1912. chrini1:stosb                ; copy value to char set table
  1913.     inc    al
  1914.     loop    chrini1
  1915.     mov    di,setptr
  1916.     mov    byte ptr[di+gsize],94    ; say this is a 94 byte set
  1917.     mov    word ptr[di+gsize+1],0+'B' ; set ident code to ASCII "B"
  1918.     pop    es
  1919.     pop    di
  1920.     pop    cx
  1921.     pop    ax
  1922.     ret
  1923. chrinit    endp
  1924.  
  1925. ; copy gsize+3 bytes from (si) to (setptr)
  1926. cpyset    proc    near
  1927.     push    es
  1928.     push    ds
  1929.     pop    es
  1930.     cld
  1931.     mov    cx,gsize+3        ; gsize chars plus three ident bytes
  1932.     mov    di,setptr        ; destination
  1933.     rep    movsb
  1934.     pop    es
  1935.     ret
  1936. cpyset    endp
  1937.  
  1938. ; Move National Replacement Characters into all four tables.
  1939. ; Turns off vscntl (8-bit controls).
  1940. ; Places NRC chars in G0set, G1set, G2set, and G3set tables.
  1941. ; Also allows selection of ALT-ROM the same way, does not turn off vscntl.
  1942. setnrc    proc    near
  1943.     mov    cl,vtemu.vtchset    ; get country number
  1944.     xor    ch,ch
  1945.     or    cl,cl
  1946.     jnz    setnrc7
  1947.     ret                ; 0 is out of range
  1948. setnrc7:cmp    cl,12            ; 1-12 is the range
  1949.     jbe    setnrc1            ; be = in range
  1950.     cmp    vtemu.vtchset,13    ; want ALT-ROM?
  1951.     jne    setnrc8            ; ne = no
  1952.     mov    inter,'('        ; say ALT-ROM in G0 set
  1953.     mov    ninter,1        ; one intermediate char
  1954.     jmp    atdgf1            ; do ALT-ROM setup
  1955.  
  1956. setnrc8:cmp    vtemu.vtchset,14    ; Transparent (14)?
  1957.     jne    setnrc4            ; ne = no, unknown
  1958.     mov    inter,'.'        ; say 96 byte transparent in G2 set
  1959.     mov    ninter,1        ; one intermediate char
  1960.     jmp    atdgfq            ; do Transparent setup
  1961.  
  1962. setnrc1:test    vtemu.vtflgop,vsnrcm    ; doing National Replacement Chars?
  1963.     jz    setnrc4            ; z = no
  1964.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls
  1965.     mov    setptr,offset G0set    ; destination, do G0set
  1966.     call    setnrc5            ; do the setup
  1967.     mov    setptr,offset G1set    ; do G1set
  1968.     call    setnrc5            ; do the setup
  1969.     test    flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
  1970.     jz    setnrc4            ; z = no, no NRCs to G2 and G3
  1971. setnrc2:mov    setptr,offset G2set    ; do G2set
  1972.     call    setnrc5            ; do the setup
  1973.     mov    setptr,offset G3set    ; do G3set
  1974.     call    setnrc5            ; do the setup
  1975. setnrc4:ret
  1976.  
  1977. ; worker routine. Enter with CX holding country number 1..12
  1978. setnrc5:push    bx
  1979.     push    cx
  1980.     push    si
  1981.     push    di
  1982.     call    chrinit            ; init table to ascii
  1983.         ; copy from NRC table (si) to set pointed at by di, cx chars
  1984.                     ;  plus 3 ident bytes at table end.
  1985.     call    nrc2cp            ; set si to NRC table
  1986.     mov    bx,si            ; bx = location of old chars
  1987.     sub    si,cx            ; minus one
  1988.     shl    cx,1            ; 15 bytes per NRC entry
  1989.     shl    cx,1
  1990.     shl    cx,1
  1991.     shl    cx,1
  1992.     add    si,cx            ; +16, source, point at this entry
  1993.     mov    cx,12            ; do first 12 bytes of them
  1994.     push    es
  1995.     mov    ax,ds
  1996.     mov    es,ax
  1997.     cld
  1998.     xor    ah,ah
  1999. setnrc6:mov    al,[bx]            ; get location of new char
  2000.     inc    bx
  2001.     mov    di,setptr        ; start of destination table
  2002.     add    di,ax            ; destination of new char
  2003.     movsb                ; move replacement char from nrc list
  2004.     loop    setnrc6
  2005.     mov    di,setptr
  2006.     add    di,gsize        ; look at end of set, to id bytes
  2007.     movsw                ; copy set size and two ident chars
  2008.     movsb
  2009.     pop    es
  2010.     pop    di
  2011.     pop    si
  2012.     pop    cx
  2013.     pop    bx
  2014.     ret
  2015. setnrc    endp
  2016.  
  2017. ; Routine to set default character set.
  2018. chrdef    proc    near
  2019.       mov    GLptr,offset G0set    ; map G0 set to GLeft
  2020.     mov    GRptr,offset G2set    ; map G2 set to GRight
  2021.     mov    SSptr,0            ; clear single shift
  2022.     test    vtemu.vtflgop,vsnrcm    ; NRC's active?
  2023.     jz    chrdef1            ; z = no
  2024.     jmp    setnrc            ; nz = yes, set them
  2025. chrdef1:mov    setptr,offset G0set
  2026.     call    chrinit            ; make ASCII
  2027.     cmp    vtemu.vtchset,13    ; want default of ALT-ROM or Transpar
  2028.     jne    chrdef2            ; ne = no
  2029.     call    setnrc            ; use NRC code to setup G0
  2030. chrdef2:mov    setptr,offset G1set
  2031.     mov    si,offset G0set
  2032.     call    cpyset            ; copy G0set to G1set
  2033.     mov    setptr,offset G2set
  2034.     call    chrinit            ; make G2 = ASCII
  2035.     test    flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
  2036.     jz    chrdef3            ; z = no, make G2 = G3 = ASCII
  2037.     call    latin1            ; set si to Latin-1 table offset
  2038.     cmp    vtemu.vtchset,15    ; SET TERM CHAR LATIN-1?
  2039.     je    chrdef2a        ; e = yes
  2040.     call    decsupg            ; else DEC Supplement Graph (DEC-MCS)
  2041.     cmp    vtemu.vtchset,0        ; SET TERM CHAR ASCII?
  2042.     je    chrdef3            ; e = yes, ascii in both halves
  2043. chrdef2a:call    cpyset            ; copy Latin-1 to G2
  2044. chrdef3:mov    setptr,offset G3set
  2045.     mov    si,offset G2set
  2046.     call    cpyset            ; copy G2set to G3set
  2047.     cmp    vtemu.vtchset,14    ; SET TERM CHAR TRANSPARENT?
  2048.     jne    chrdef4            ; ne = no
  2049.     mov    setptr,offset G2set
  2050.     call    setnrc            ; use NRC code to setup G2
  2051.     mov    setptr,offset G1set
  2052.     mov    si,offset G2set
  2053.     call    cpyset            ; copy G2set to G1set for VT100's
  2054.     ret
  2055. chrdef4:call    decsupg            ; source data is DEC Supplement Gr.
  2056.     cmp    word ptr upss+1,'5%'    ; DEC Supplemental Graphics?
  2057.     jne    chrdef5            ; ne = no
  2058.     mov    setptr,offset G2set    ; G2 to DEC Supp Gr
  2059.     call    cpyset            ; copy the set
  2060.     mov    setptr,offset G3set    ; G3 to DEC Supp Gr
  2061.     call    cpyset
  2062.  
  2063. chrdef5:mov    cx,4            ; do table overrides
  2064.     mov    setptr,offset G0set    ; first table pointer
  2065.     mov    bx,offset vtemu.vttable    ; table of char set overrides
  2066. chrdef6:mov    al,[bx]            ; get an override char set number
  2067.     inc    bx            ; ready for next item next time
  2068.     push    bx
  2069.     push    cx
  2070.     cmp    al,0ffh            ; none?
  2071.     je    chrdef11        ; e = none
  2072.     or    al,al            ; just ASCII?
  2073.     jnz    chrdef6a        ; nz = no
  2074.     call    chrinit            ; make ASCII
  2075.     jmp    short chrdef99
  2076.  
  2077. chrdef6a:cmp    al,12            ; in NRC's
  2078.     ja    chrdef7            ; a = no
  2079.     mov    cl,al            ; put country number in cx
  2080.     xor    ch,ch
  2081.     call    setnrc5            ; setup an NRC, using cx and setptr
  2082.     jmp    short chrdef99
  2083.  
  2084. chrdef7:cmp    al,13            ; want ALT-ROM?
  2085.     jne    chrdef8            ; ne = no
  2086.     sub    cx,4            ; compute set number 0..4
  2087.     neg    cx            ; 4 - cx
  2088.     add    cl,'('            ; designator characters
  2089.     mov    inter,cl        ; say ALT-ROM in Gn set
  2090.     mov    ninter,1        ; one intermediate char
  2091.     call    atdgf1            ; do ALT-ROM setup
  2092.     jmp    short chrdef99
  2093.  
  2094. chrdef8:cmp    al,14            ; Transparent (14)?
  2095.     jne    chrdef9            ; ne = no
  2096.     sub    cx,4            ; cx - 4, compute set number 0..4
  2097.     neg    cx            ; 4 - cx
  2098.     add    cl,'-' -1        ; designator characters
  2099.     mov    inter,cl        ; say 96 byte transparent in Gn set
  2100.     mov    ninter,1        ; one intermediate char
  2101.     call    atdgfq            ; do Transparent setup
  2102.     jmp    short chrdef99
  2103.  
  2104. chrdef9:cmp    setptr,offset G0set    ; want 96 byte set in G0?
  2105.     je    chrdef11        ; e = yes, can not do this
  2106.     cmp    al,15            ; Latin1?
  2107.     jne    chrdef10        ; ne = no
  2108.     call    latin1            ; set si to Latin-1 table offset
  2109.     jmp    short chrdef10a
  2110.  
  2111. chrdef10:cmp    al,16            ; DEC-MCS?
  2112.     jne    chrdef11        ; ne = no
  2113.     call    decsupg            ; DEC Supplement Graph (DEC-MCS)
  2114. chrdef10a:call    cpyset            ; copy the char set
  2115.     jmp    short chrdef99
  2116.     
  2117. chrdef11:cmp    al,18            ; DEC-Special-Graphics?
  2118.     jne    chrdef99        ; ne = no
  2119.     sub    cx,4            ; compute set number 0..4
  2120.     neg    cx            ; 4 - cx
  2121.     add    cl,'('            ; 94 set designator characters
  2122.     mov    inter,cl        ; say DEC-Special-Graphics in Gn set
  2123.     mov    ninter,1        ; one intermediate char
  2124.     call    atdgf0
  2125.     
  2126. chrdef99:pop    cx
  2127.     pop    bx
  2128.     add    setptr,gsize+3        ; next Gn pointer
  2129.     dec    cx
  2130.     or    cx,cx
  2131.     jle    chrdef100        ; le = end of loop
  2132.     jmp    chrdef6
  2133. chrdef100:
  2134.     ret
  2135. chrdef    endp
  2136.  
  2137. ; Set register SI to the offset of the ISO Latin-1 table appropriate to the
  2138. ; currently active Code Page. Defaults to CP437 if no CP found.
  2139. LATIN1    proc    near
  2140.     push    bx
  2141.     push    dx
  2142.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  2143.     jb    latin1a            ; b = no, no Code Pages
  2144.     mov    ax,6601h        ; get global Code Page
  2145.     int    dos            ; bx=active Code Page, dx=boot CP
  2146.     cmp    bx,437            ; current Code Page is 437?
  2147.     je    latin1a            ; e = yes
  2148.     mov    si,offset L1cp850    ; assume CP850
  2149.     cmp    bx,850            ; current Code Page is 850?
  2150.     je    latin1x            ; e = yes
  2151.     mov    si,offset L1cp860    ; assume CP860
  2152.     cmp    bx,860            ; current Code Page is 860?
  2153.     je    latin1x            ; e = yes
  2154.     mov    si,offset L1cp863    ; assume CP863
  2155.     cmp    bx,863            ; current Code Page is 863?
  2156.     je    latin1x            ; e = yes
  2157.     mov    si,offset L1cp865    ; assume CP865
  2158.     cmp    bx,865            ; current Code Page is 865?
  2159.     je    latin1x            ; e = yes
  2160. latin1a:mov    si,offset L1cp437    ; default to CP437
  2161. latin1x:pop    dx
  2162.     pop    bx
  2163.     ret
  2164. LATIN1    endp
  2165.  
  2166. ; Set register SI to the offset of the DEC Multinational char set (DEC
  2167. ; Supplemental Graphics) table appropriate to the currently active Code Page.
  2168. ; Defaults to CP437 if no CP found.
  2169. DECSUPG    proc    near
  2170.     push    bx
  2171.     push    dx
  2172.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  2173.     jb    decsu1a            ; b = no, no Code Pages
  2174.     mov    ax,6601h        ; get global Code Page
  2175.     int    dos            ; bx=active Code Page, dx=boot CP
  2176.     cmp    bx,437            ; current Code Page is 437?
  2177.     je    decsu1a            ; e = yes
  2178.     mov    si,offset MNcp850    ; assume CP850
  2179.     cmp    bx,850            ; current Code Page is 850?
  2180.     je    decsu1x            ; e = yes
  2181.     mov    si,offset MNcp860    ; assume CP860
  2182.     cmp    bx,860            ; current Code Page is 860?
  2183.     je    decsu1x            ; e = yes
  2184.     mov    si,offset MNcp863    ; assume CP863
  2185.     cmp    bx,863            ; current Code Page is 863?
  2186.     je    decsu1x            ; e = yes
  2187.     mov    si,offset MNcp865    ; assume CP865
  2188.     cmp    bx,865            ; current Code Page is 865?
  2189.     je    decsu1x            ; e = yes
  2190. decsu1a:mov    si,offset MNcp437    ; default to CP437
  2191. decsu1x:pop    dx
  2192.     pop    bx
  2193.     ret
  2194. DECSUPG    endp
  2195.  
  2196. ; Set reg BX to offset of table for Code Page to DEC Multinational Char Set
  2197. ; (DEC Supplemental Graphics)
  2198. CPDECSG proc    near
  2199.     mov    bx,offset cp437MN    ; assume CP437
  2200.     cmp    flags.chrset,437    ; current Code Page is 437?
  2201.     je    cpdecsx            ; e = yes
  2202.     mov    bx,offset cp850MN    ; assume CP850
  2203.     cmp    flags.chrset,850    ; current Code Page is 850?
  2204.     je    cpdecsx            ; e = yes
  2205.     mov    bx,offset cp860MN    ; assume CP860
  2206.     cmp    flags.chrset,860    ; current Code Page is 860?
  2207.     je    cpdecsx            ; e = yes
  2208.     mov    bx,offset cp863MN    ; assume CP863
  2209.     cmp    flags.chrset,863    ; current Code Page is 863?
  2210.     je    cpdecsx            ; e = yes
  2211.     mov    bx,offset cp865MN    ; assume CP865
  2212.     cmp    flags.chrset,865    ; current Code Page is 865?
  2213.     je    cpdecsx            ; e = yes
  2214.     mov    bx,offset cp437MN    ; default to CP437
  2215. CPDECSX:ret
  2216. CPDECSG endp
  2217.  
  2218. ; Set register SI to the offset of the NRC table appropriate to the
  2219. ; currently active Code Page. Defaults to CP437 if no CP found.
  2220. NRC2CP    proc    near
  2221.     push    bx
  2222.     push    dx
  2223.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  2224.     jb    nrc2cp1            ; b = no, no Code Pages
  2225.     mov    ax,6601h        ; get global Code Page
  2226.     int    dos            ; bx=active Code Page, dx=boot CP
  2227.     cmp    bx,437            ; current Code Page is 437?
  2228.     je    nrc2cp1            ; e = yes
  2229.     mov    si,offset NRC850    ; assume CP850
  2230.     cmp    bx,850            ; current Code Page is 850?
  2231.     je    nrc2cpx            ; e = yes
  2232.     mov    si,offset NRC860    ; assume CP860
  2233.     cmp    bx,860            ; current Code Page is 860?
  2234.     je    nrc2cpx            ; e = yes
  2235.     mov    si,offset NRC863    ; assume CP863
  2236.     cmp    bx,863            ; current Code Page is 863?
  2237.     je    nrc2cpx            ; e = yes
  2238.     mov    si,offset NRC865    ; assume CP865
  2239.     cmp    bx,865            ; current Code Page is 865?
  2240.     je    nrc2cpx            ; e = yes
  2241. nrc2cp1:mov    si,offset NRC437    ; default to CP437
  2242. nrc2cpx:pop    dx
  2243.     pop    bx
  2244.     ret
  2245. NRC2CP    endp
  2246.  
  2247.  
  2248. ; cursor movements
  2249.  
  2250. atcup:    test    dspstate,dsptype    ; on VT320 status line?
  2251.     jz    atcup0            ; z = no
  2252.     mov    param,0            ; yes, do not change rows
  2253. atcup0:    mov    dh,byte ptr param    ; get row,col parameters
  2254.     mov    dl,byte ptr param+2    ; dh is row, dl is column
  2255.     or    dh,dh            ; zero row number?
  2256.     jz    atcup1            ; z = yes, continue
  2257.     dec    dh            ; normalize to 0,0 system
  2258. atcup1:    or    dl,dl            ; ditto for column
  2259.     jz    atcup2
  2260.     dec    dl
  2261. atcup2:    test    vtemu.vtflgop,decom    ; Origin mode?
  2262.     jz    atcup3            ; z = no, skip this stuff
  2263.     add    dh,mar_top        ; yes, it was relative to top margin
  2264.     jno    atcup3            ; if no overflow, continue
  2265.     mov    dh,byte ptr low_rgt+1    ; otherwise just set to screen bottom
  2266. atcup3:    mov    al,byte ptr low_rgt    ; right margin
  2267.     cmp    dl,al            ; too far to the right?
  2268.     jbe    atcup4            ; ne = no
  2269.     mov    dl,al            ; limit to right margin
  2270. atcup4:    mov    ah,byte ptr low_rgt+1    ; last regular text line
  2271.     cmp    dh,ah            ; going to 25th line?
  2272.     jbe    atcup7            ; be = no
  2273.     inc    ah            ; "25th" status line
  2274.     cmp    flags.vtflg,ttheath    ; emulating a Heath-19?
  2275.     je    atcup5            ; e = yes
  2276.     cmp    dh,ah            ; going too far?
  2277.     je    atcup8            ; e = no
  2278.     dec    ah
  2279.     mov    dh,ah            ; last normal row
  2280.     jmp    atscu5            ; set cursor here
  2281. atcup5:    cmp    dh,ah            ; going too far?
  2282.     ja    atcup6            ; a = yes
  2283.     test    h19stat,h19l25        ; Heath 25th mode line enabled?
  2284.     jnz    atcup8            ; nz = yes
  2285. atcup6:    mov    dh,byte ptr cursor+1    ; do not change rows
  2286. atcup7: call    atccpc            ; check position
  2287. atcup8:    jmp    atscu5            ; set cursor position and return
  2288.  
  2289. atcuarg:mov    al,byte ptr param    ; worker, get cursor movement argument
  2290.     or    al,al            ; zero?
  2291.     jnz    atcua1            ; nz = no
  2292.     inc    al            ; default to one
  2293. atcua1: ret
  2294.                     ; cursor up
  2295. atcuu:    cmp    dh,byte ptr low_rgt+1    ; on 25th line?
  2296.     jbe    atcuu1            ; be = no
  2297.     ret                ; no vertical for Heath on 25th line
  2298. atcuu1:    call    atcuarg            ; get cursor move up argument into al
  2299.     sub    dh,al            ; compute new cursor position
  2300.     jnc    atcuu2            ; nc = ok [dlk]
  2301.     xor    dh,dh            ; overflow, restrict range. [dlk]
  2302. atcuu2:    call    atccic            ; check indexing, ignore action in ax
  2303.     jmp    atscu5            ; set the cursor at its new position
  2304.  
  2305. atcud:    call    atcuarg            ; cursor down
  2306.     cmp    dh,byte ptr low_rgt+1    ; on 25th line now?
  2307.     jbe    atcud1            ; be = no
  2308.     ret                ; else leave it on status line
  2309. atcud1:    add    dh,al            ; compute new cursor position
  2310.     jnc    atcud2            ; nc = ok [dlk]
  2311.     mov    dh,byte ptr low_rgt+1    ; default bottom [dlk]
  2312. atcud2:    call    atccic            ; check indexing, ignore action in ax
  2313.     jmp    atscu5            ; set the cursor at its new position
  2314.  
  2315.                     ; Allow horiz movement on 25th line
  2316. atcuf:    call    atcuarg            ; cursor forward
  2317.     add    dl,al            ; compute new cursor position
  2318.     jnc    atcup3            ; nc = no problem
  2319.     mov    dl,byte ptr low_rgt    ; else set to right margin
  2320.     jmp    atcup3            ; check/set cursor, return
  2321.  
  2322. atcub:    call    atcuarg            ; cursor back
  2323.     sub    dl,al            ; compute new cursor position
  2324.     jnc    atcub1            ; nc = no problem
  2325.     xor    dl,dl            ; else set to left margin
  2326. atcub1:    jmp    atcup3            ; check/set cursor, return
  2327.  
  2328. atcha:    call    atcuarg            ; absolute horizontal address
  2329.     mov    dl,al            ; new column, counted from 1
  2330.     sub    dl,1            ; column, count from 0 internally
  2331.     jns    atcha1            ; ns = no problem
  2332.     xor    dl,dl            ; else set to left margin
  2333. atcha1:    jmp    atcup3            ; check/set cursor, return
  2334.  
  2335. atcht:    call    atcuarg            ; move cursor forward # horiz tabs
  2336.     inc    dl            ; next column
  2337.     mov    cl,al            ; number of tabstops to locate
  2338.     xor    ch,ch
  2339.     mov    si,offset tabs        ; active tabs buffer
  2340. atcht1:    cmp    dl,byte ptr low_rgt    ; at end of line?
  2341.     jae    atcht2            ; ae = yes, stop here
  2342.     call    istabs            ; is dl column a tabstop?
  2343.     inc    dl            ; try next column, preserves carry
  2344.     jnc    atcht1            ; nc = no, find one
  2345.     loop    atcht1            ; do cx tabstops
  2346. atcht2:    jmp    atcup3            ; set cursor
  2347.  
  2348. atcva:    inc    dl            ; count columns from 1 here
  2349.     mov    byte ptr param+2,dl    ; set column in second parameter
  2350.     mov    param+3,0        ; high byte
  2351.     jmp    atcup            ; do absolute vertical positioning
  2352.  
  2353. atcnl:    call    atcuarg            ; do # Next-Lines
  2354.     cmp    dh,byte ptr low_rgt+1    ; on 25th line now?
  2355.     jbe    atcnl1            ; be = no
  2356.     ret                ; else leave it on status line
  2357. atcnl1:    mov    cl,al            ; number to do
  2358.     xor    ch,ch
  2359. atcnl2:    push    cx
  2360.     inc    dh            ; number to do
  2361.     xor    dl,dl            ; cursor to left margin
  2362.     call    atccic            ; check cursor position
  2363.     call    ax            ; scroll if necessary
  2364.     call    atscu5            ; set cursor, etc. and return
  2365.     pop    cx
  2366.     loop    atcnl2
  2367.     ret
  2368. atcpl:    call    atcuarg            ; do # Previous-Lines
  2369.     cmp    dh,byte ptr low_rgt+1    ; on 25th line now?
  2370.     jbe    atcpl1            ; be = no
  2371.     ret                ; else leave it on status line
  2372. atcpl1:    mov    cl,al            ; number to do
  2373.     xor    ch,ch
  2374.     xor    dl,dl            ; set to column zero
  2375. atcpl2:    dec    dh            ; do one line
  2376.     push    cx            ; save counter
  2377.     call    atccic            ; check cursor position
  2378.     call    ax            ; scroll if necessary
  2379.     call    atscu5            ; set cursor
  2380.     pop    cx
  2381.     loop    atcpl2            ; do cx times
  2382.     ret
  2383.  
  2384. ; Screen erasure commands
  2385.                     ; Erase in display
  2386. ated:    cmp    ninter,0        ; zero intermediates?
  2387.     je    ated0            ; e = yes, else quit
  2388.     ret
  2389.  
  2390. ated0:    cmp    param,0            ; was arg zero?
  2391.     jne    ated1            ; ne = no
  2392.     jmp    ereos            ; do erase cursor to end of screen
  2393.  
  2394. ated1:    cmp    param,1            ; was arg one?
  2395.     jne    ated2            ; ne = no
  2396.     jmp    ersos            ; do erase start of screen to cursor
  2397.  
  2398. ated2:    cmp    param,2            ; was arg two?
  2399.     je    ated2a            ; e = yes, erase entire screen
  2400.     ret                ; else ignore
  2401. ated2a:    push    dx            ; save dynamic cursor
  2402.     xor    dx,dx            ; say cursor is at 0,0
  2403.     call    ereos            ; erase cursor to end of screen
  2404.     pop    dx            ; recover cursor
  2405.     ret
  2406.                     ; Erase in current line
  2407. atel:    cmp    ninter,0        ; zero intermediates?
  2408.     je    atel0            ; e = yes, else quit
  2409.     ret
  2410.  
  2411. atel0:    cmp    param,0            ; was arg zero?
  2412.     jne    atel1            ; ne = no
  2413.     mov    al,dl            ; erase from cursor
  2414.     mov    bl,crt_cols        ;  to end of line, inclusive
  2415.     dec    bl            ; physical line
  2416.     jmp    erinline        ; do the erasure
  2417.  
  2418. atel1:    cmp    param,1            ; was arg one?
  2419.     jne    atel2            ; ne = no
  2420.     xor    al,al            ; erase from start of line
  2421.     mov    bl,dl            ;  to cursor, inclusive
  2422.     jmp    erinline        ; do the erasure
  2423.  
  2424. atel2:    cmp    param,2            ; was arg two?
  2425.     jne    atel3            ; ne = no, ignore
  2426.     xor    al,al            ; erase entire line
  2427.     mov    bl,crt_cols
  2428.     dec    bl            ; physical line
  2429.     jmp    erinline        ; clear it
  2430. atel3:    ret
  2431.                     ; ECH, erase chars in this line
  2432. atech:    mov    ax,dx            ; get cursor position
  2433.     mov    bx,ax            ; erase ax to bx
  2434.     cmp    byte ptr param,0    ; 0 argument
  2435.     je    atech1            ; e = yes
  2436.     dec    bl            ; count from 1
  2437. atech1:    add    bl,byte ptr param    ; number of characters
  2438.     jmp    erinline        ; erase in this line
  2439.  
  2440. ; Set Graphics Rendition commands (video attributes)
  2441.  
  2442. atsgr:    cmp    lparam,0        ; any letter parameter?
  2443.     jne    atsgr0            ; ne = yes, fail
  2444.     mov    ah,curattr        ; get current cursor attribute
  2445.     mov    di,offset atsgr1    ; routine to call
  2446.     call    atreps            ; repeat for all parms
  2447.     mov    curattr,ah        ; store new attribute byte
  2448. atsgr0:    ret
  2449.  
  2450. atsgr1: mov    bx,param[si]        ; fetch an argument
  2451.     or    bl,bl            ; 0, clear all attributes?
  2452.     jnz    atsgr2            ; nz = no, do selectively below
  2453. ;    call    clrbold            ; clear bold attribute
  2454. ;    call    clrblink        ; clear blink attribute
  2455. ;    call    clrunder        ; clear underline attribute
  2456.     call    clrrev            ; clear reverse video attribute
  2457.            mov    ah,att_normal        ; get present normal coloring
  2458.     test    vtemu.vtflgop,vsscreen    ; want reverse video?
  2459.     jz    atsgr1a            ; z = no
  2460.     call    revideo            ; reverse the attributes
  2461. atsgr1a:mov    scbattr,ah        ; set background attributes
  2462.     mov    curattr,ah        ; and cursor attributes
  2463.     ret
  2464.  
  2465. atsgr2: cmp    bl,1            ; 1, set bold?
  2466.     jne    atsgr3            ; ne = no
  2467.     jmp    setbold            ; set bold attribute
  2468.  
  2469. atsgr3: cmp    bl,4            ; 4, set underline?
  2470.     jne    atsgr4            ; ne = no
  2471.     jmp    setunder        ; set underline attribute
  2472.  
  2473. atsgr4: cmp    bl,5            ; 5, set blink?
  2474.     jne    atsgr5            ; ne = no
  2475.     jmp    setblink        ; set blink attribute
  2476.  
  2477. atsgr5: cmp    bl,7            ; 7, reverse video for chars?
  2478.     jne    atsgr6            ; ne = no, try coloring
  2479.     jmp    setrev            ; set reversed video attribute (AH)
  2480.  
  2481. atsgr6:    cmp    flags.vtflg,ttheath    ; Heath-19?
  2482.     jne    atsgr9            ; ne = no
  2483.     cmp    bl,10            ; 10, enter graphics mode?
  2484.     jne    atsgr7            ; ne = no
  2485.     push    ax            ; save ah
  2486.     mov    al,'F'            ; simulate final char of 'F'
  2487.     call    v52sgm            ; do character setup like VT52
  2488.     pop    ax
  2489.     ret
  2490. atsgr7:    cmp    bl,11            ; 11, exit graphics mode?
  2491.     jne    atsgr8            ; ne = no, ignore
  2492.     push    ax            ; save ah
  2493.     mov    al,'G'            ; simulate final char of 'G'
  2494.     call    v52sgm            ; do character setup like VT52
  2495.     pop    ax
  2496. atsgr8:    ret
  2497.  
  2498. atsgr9:    test    flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
  2499.     jz    atsgr8            ; z = no, 22-27 are VT220/320 only
  2500.     cmp    bl,22            ; 22, bold off?
  2501.     jne    atsgr10            ; ne = no
  2502.     jmp    clrbold
  2503. atsgr10:cmp    bl,24            ; 24, underline off?
  2504.     jne    atsgr11            ; ne = no
  2505.     jmp    clrunder
  2506. atsgr11:cmp    bl,25            ; 25, blinking off?
  2507.     jne    atsgr12            ; ne = no
  2508.     jmp    clrblink
  2509. atsgr12:cmp    bl,27            ; 27, reverse video off?
  2510.     jne    atsgr13            ; ne = no
  2511.     jmp    clrrev            ; clear reversed video attribute (AH)
  2512. atsgr13:jmp    setcolor        ; BL = color, AH = attribute byte
  2513.  
  2514. ; Tabulation char commands
  2515. attbc:    call    atccpc            ; make sure cursor is kosher
  2516.     cmp    ninter,0        ; zero intermediates?
  2517.     je    attbc0            ; e = yes, else quit
  2518.     ret
  2519.                     ; Tabstop set/clears
  2520. attbc0: cmp    param,0            ; was argument zero?
  2521.     jne    attbc1            ; ne = no
  2522.     push    si
  2523.     mov    si,vtemu.vttbst        ; active buffer
  2524.     call    tabclr            ; clear tabstop in column DL
  2525.     pop    si
  2526.     ret
  2527.  
  2528. attbc1: cmp    param,3            ; was arg 3 (clear all tab stops)?
  2529.     je    attbc2            ; e = yes
  2530.     ret                ; else ignore
  2531. attbc2:    mov    cx,(swidth+7)/8        ; get ready to zap swidth columns
  2532.     mov    di,offset tabs        ; point to the tab stop table
  2533.     xor    al,al            ; zero indicates no tab stop
  2534.     push    es            ; save es
  2535.     push    ds
  2536.     pop    es            ; use data segment for es:di below
  2537.     cld                ; set direction forward
  2538.     rep    stosb            ; clear all bits
  2539.     pop    es
  2540.     ret
  2541.                     ; set scrolling margins
  2542. atstbm:    test    dspstate,dsptype    ; on status line?
  2543.     jnz    atstb3            ; nz = yes, ignore this command
  2544.     mov    al,byte ptr param    ; get the two line number args
  2545.     mov    ah,byte ptr param+2
  2546.     or    al,al            ; was first zero?
  2547.     jnz    atstb1            ; nz = no, continue
  2548.     inc    al            ; default is one
  2549. atstb1: or    ah,ah            ; was second zero?
  2550.     jnz    atstb2            ; nz = no
  2551.     mov    ah,byte ptr low_rgt+1    ; yes, default is last line on screen
  2552.     inc    ah
  2553. atstb2: dec    al            ; normalize to 0,0 coordinate system
  2554.     dec    ah
  2555.     cmp    ah,al            ; size of region at least two lines?
  2556.     jbe    atstb3            ; be = no, indicate an error
  2557.     or    al,al            ; check against screen limits
  2558.     jl    atstb3            ; l = out of range
  2559.     cmp    ah,byte ptr low_rgt+1
  2560.     ja    atstb3            ; a = too far down
  2561.     mov    mar_top,al        ; set the limits
  2562.     mov    mar_bot,ah
  2563.     xor    dx,dx            ; Home cursor
  2564.     jmp    atscu5            ; set cursor position and return
  2565. atstb3:    ret                ; ignore bad requests
  2566.  
  2567. ; Device attributes commands
  2568. atda:    cmp    param,0            ; was argument zero?
  2569.     je    decid            ; e = send the i.d. string
  2570.     ret                ; no, only an echo
  2571. decid:    cmp    ninter,0        ; any intermediates?
  2572.     je    decid1            ; e = no, else not this item
  2573.     jmp    atdgnrc            ; try Spanish NRC designator
  2574. decid1:    mov    al,flags.vtflg        ; get terminal ident type
  2575.     mov    cx,20            ; assumed length of asciiz string
  2576.     mov    si,offset v32str    ; VT320 ident string
  2577.     cmp    al,ttvt320        ; VT320?
  2578.     je    decid2            ; e = yes
  2579.     mov    si,offset v22str
  2580.     cmp    al,ttvt220        ; VT220?
  2581.     je    decid2            ; e = yes
  2582.     mov    si,offset v102str
  2583.     cmp    al,ttvt102        ; VT102?
  2584.     je    decid2            ; e = yes
  2585.     mov    si,offset v100str
  2586.     cmp    al,ttvt100        ; VT100?
  2587.     je    decid2            ; e = yes
  2588.     cmp    al,tthoney        ; Honeywell?
  2589.     je    decid2            ; e = yes
  2590.     mov    si,offset v52str
  2591.     cmp    al,ttvt52        ; Heath-19 mode?
  2592.     je    decid2            ; e = yes
  2593.     mov    si,offset h19str
  2594. decid2:    cmp    lparam,'>'        ; this letter parameter?
  2595.     jne    decid3            ; ne = no
  2596.     test    al,ttvt320+ttvt220    ; VT320/VT220 mode?
  2597.     jz    decid4            ; z = no, ignore
  2598.     mov    si,offset v32sda    ; Secondary DA response string
  2599. decid3:    cld
  2600.     lodsb                ; read string
  2601.     or    al,al            ; end of string?
  2602.     jz    decid4            ; z = yes
  2603.     push    cx
  2604.     push    si
  2605.     call    prtbout            ; send it to port with no local echo
  2606.     pop    si
  2607.     pop    cx
  2608.     loop    decid3            ; do all characters
  2609. decid4:    ret
  2610.                     ; Display LED's
  2611. atll:    mov    di,offset atleds    ; get pointer to routine to call
  2612.     call    atreps            ; repeat for selective parameters
  2613.     ret
  2614.  
  2615. atleds:    push    si            ; set LED indicators
  2616.     call    getled            ; set si to term type (led) string
  2617.     mov    di,si
  2618.     pop    si
  2619.     jc    atled2            ; c = no leds 1..4, ignore
  2620. atled4:    cmp    param[si],0        ; zero argument?
  2621.     jne    atled3            ; ne = no, check further
  2622.     mov    al,led_off        ; set all off
  2623.     mov    ah,al
  2624.     mov    [di+6],ax        ; where dots go after name
  2625.     mov    [di+6+2],ax
  2626. atled1: jmp    ansdsl            ; update "LEDs" display and return
  2627. atled2: ret
  2628. atled3: mov    ax,param[si]        ; get the argument
  2629.     cmp    al,1            ; must be 1 to 4
  2630.     jb    atled2            ; b = out of range
  2631.     cmp    al,4
  2632.     ja    atled2            ; a = out of range
  2633.     dec    ax            ; zero base it
  2634.     push    di
  2635.     add    di,ax
  2636.     add    al,'1'            ; add ascii offset for digit
  2637.     mov    [di+6],al         ; turn the "LED" on by storing digit
  2638.     pop    di
  2639.     jmp    short atled1        ; update display and return
  2640.  
  2641.  
  2642. ; Set/Reset mode commands
  2643.                     ; ESC [ ? xxx h/l Set/Reset series
  2644. atrm:    mov    modeset,0        ; say we are resetting modes
  2645.     mov    di,offset atrsm        ; Reset/Set modes
  2646.     call    atreps            ; repeat for all parms
  2647.     test    vtemu.vtflgop,decanm    ; did ansi mode get reset?
  2648.     jnz    atrm1            ; nz = no, return
  2649.     cmp    flags.vtflg,ttheath    ; were we a Heath-19?
  2650.     je    atrm0            ; e = yes, don't change terminal types
  2651.     mov    flags.vtflg,ttvt52    ; say VT52 now
  2652. atrm0:    call    chrdef            ; set default char sets
  2653.     call    atsc            ; save cursor status
  2654.     call    ansdsl            ; update terminal type
  2655. atrm1:    ret
  2656.  
  2657. atsm:    mov    modeset,1        ; say we are setting modes
  2658.     mov    di,offset atrsm        ; Reset/Set modes
  2659.     jmp    atreps            ; repeat for all parms
  2660.  
  2661. atrsm:    mov    ax,param[si]        ; pick up the argument
  2662.     cmp    lparam,'?'        ; DEC private mode? ESC [ ?
  2663.     je    atrsm1            ; e = yes, do DEC specific things
  2664.     cmp    lparam,'>'        ; Heath-19 private mode? ESC [ >
  2665.     jne    atrsma            ; ne = no
  2666.     jmp    htrsm1            ; do Heath specific things
  2667.                     ; ANSI level
  2668. atrsma:    cmp    al,20            ; 20, ANSI new-line mode?
  2669.     jne    atrsm0            ; ne = no, try insert mode
  2670.     and    vtemu.vtflgop,not vsnewline ; assume resetting
  2671.     cmp    modeset,0        ; resetting?
  2672.     je    atrsmb            ; e = yes
  2673.     or    vtemu.vtflgop,vsnewline    ; setting
  2674. atrsmb:    mov    ax,anslnm        ; get the flag bit
  2675.     jmp    atrsflg            ; set or reset it
  2676. atrsm0:    cmp    al,4            ; toggle insert mode?
  2677.     jne    atrsmc            ; ne = no
  2678.     mov    al,modeset        ; set/reset insert mode
  2679.     mov    insmod,al        ; store it
  2680.     ret
  2681. atrsmc:    cmp    al,12            ; 12? Control local echo
  2682.     jne    atrsmx            ; ne = no
  2683.     cmp    modeset,0        ; resetting mode (ESC [ 12 l)?
  2684.     jne    atrsmc1            ; ne = no
  2685.     or    vtemu.vtflgop,dececho    ; remember state here too
  2686.     or    yflags,lclecho        ; (l) turn on local echoing
  2687.     jmp    short atrsmc2
  2688. atrsmc1:and    yflags,not lclecho    ; (h) turn off local echoing
  2689.     and    vtemu.vtflgop,not dececho
  2690. atrsmc2:test    yflags,modoff        ; is mode line off?
  2691.     jnz    atrsmx            ; nz = yes
  2692.     push    dx            ; save cursor position
  2693.     call    modlin            ; write mode line
  2694.     pop    dx
  2695. atrsmx:    ret
  2696.                     ; DEC specifics
  2697. atrsm1: cmp    al,1            ; cursor keys mode?
  2698.     jne    atrsm2            ; ne = no
  2699.     mov    ax,decckm        ; get the bit
  2700.     jmp    atrsflg            ; set or reset it and return
  2701.  
  2702. atrsm2: cmp    al,7            ; Auto-wrap?
  2703.     jne    atrsm3            ; ne = no
  2704.     and    vtemu.vtflgop,not vswrap ; assume resetting line wrap
  2705.     cmp    modeset,0        ; resetting?
  2706.     je    atrsm2a            ; e = yes
  2707.     or    vtemu.vtflgop,vswrap    ; set the bit
  2708. atrsm2a:mov    ax,decawm        ; get the bit
  2709.     jmp    atrsflg            ; set or reset it and return
  2710.  
  2711. atrsm3: cmp    al,6            ; Origin mode?
  2712.     jne    atrsm4            ; ne = no
  2713.     jmp    atrsom            ; change decom and return
  2714.  
  2715. atrsm4: cmp    al,5            ; change the video?
  2716.     jne    atrsm5            ; ne = no
  2717.     jmp    atrsscnm        ; yes, change it if necessary
  2718.  
  2719. atrsm5: cmp    al,2            ; Change VT52 compatibility mode?
  2720.     jne    atrsm6            ; ne = no
  2721.     test    dspstate,dsptype    ; on status line?
  2722.     jnz    atrsm5b            ; nz = yes, ignore switch
  2723.     cmp    flags.vtflg,ttheath    ; Heath-19 mode?
  2724.     jne    atrsm5a            ; ne = no
  2725.     mov    modeset,0        ; Heath  ESC [ ? 2 h  resets ANSI mode
  2726. atrsm5a:mov    ax,decanm        ; get ansi mode flag
  2727.     jmp    atrsflg            ; set or reset it
  2728. atrsm5b:ret
  2729.  
  2730. atrsm6:    cmp    al,3            ; 132/80 column mode change?
  2731.     jne    atrsm7            ; ne = no
  2732.     mov    al,curattr        ; save current video attributes
  2733.     mov    ah,video_state        ; and rev/normal state
  2734.     push    ax
  2735.     xor    ah,ah            ; high byte: not exiting Connect mode
  2736.     mov    al,modeset        ; pass set/reset request to chgdsp[dlk]
  2737.     call    chgdsp            ; call Change Display proc in msy [dlk]
  2738.     and    vtemu.vtflgop,not deccol; assume mode is reset
  2739.     cmp    modeset,0        ; want 80 cols?
  2740.     je    atrsm6n            ; e = yes, else 132 cols
  2741.     cmp    crt_cols,80        ; see if it worked
  2742.     jbe    atrsm6b            ; be = no, do not set the status bit
  2743.     or    vtemu.vtflgop,deccol    ; set the status bit
  2744.     mov    al,crt_cols        ; get current physical screen width
  2745.     dec    al            ; we count from column 0 here
  2746.     mov    byte ptr low_rgt,al    ; screen capability
  2747.     jmp    short atrsm6e
  2748. atrsm6b:and    vtemu.vtflgst,not deccol; turn off setup 132 col bit too
  2749. atrsm6n:cmp    byte ptr low_rgt,79    ; want 80 cols, is it wider?
  2750.     jbe    atrsm6e            ; be = no
  2751.     mov    byte ptr low_rgt,79    ; narrow down to 80 columns
  2752. atrsm6e:CALL    ATRES2            ; do partial reset of emulator
  2753.     pop    ax
  2754.     mov    curattr,al        ; restore saved items
  2755.     mov    video_state,ah
  2756.     mov    dl,byte ptr low_rgt+1    ; text lines (leave status line intact)
  2757.     mov    mar_top,0
  2758.     mov    mar_bot,dl        ; reset scrolling region
  2759.     xor    dx,dx            ; new cursor position is 0,0
  2760.     mov    cursor,dx
  2761.     jmp    atscu5            ; place it there and return
  2762.  
  2763. atrsm7:    cmp    al,18            ; 18?  18 & 19 = printer support
  2764.     jne    atrsm8            ; ne = no
  2765.     cmp    modeset,0        ; resetting?
  2766.     jne    atrsm7a            ; ne = no, setting
  2767.     and    anspflg,not vtffp    ; no form feed after printing
  2768.     ret
  2769. atrsm7a:or    anspflg,vtffp        ; use form feed after printing
  2770.     ret
  2771.  
  2772. atrsm8:    cmp    al,19            ; 19, print region?
  2773.     jne    atrsm9            ; ne = no
  2774.     cmp    modeset,0        ; resetting?
  2775.     jne    atrsm8a            ; ne = no, setting
  2776.     and    anspflg,not vtextp    ; reset print region to scrolling reg
  2777.     ret
  2778. atrsm8a:or    anspflg,vtextp        ; set print region to whole screen
  2779.     ret
  2780.  
  2781. atrsm9:    cmp    al,25            ; ESC [ ? 25 h/l? cursor on/off
  2782.     jne    atrsm10            ; ne = no
  2783.     mov    al,4            ; assume cursor to be turned off (4)
  2784.     cmp    modeset,0        ; resetting (invisible cursor)?
  2785.     je    atrsm9a            ; e = yes
  2786.     mov    al,1            ; assume underline (1)
  2787.     test    vtemu.vtflgop,vscursor    ; underline?
  2788.     jnz    atrsm9a            ; nz = yes
  2789.     inc    al            ; block (2)
  2790. atrsm9a:mov    atctype,al        ; save VTxxx cursor type here
  2791.     jmp    atsctyp            ; set the cursor type
  2792.  
  2793. atrsm10:cmp    al,34            ; ESC [ ? 34 h/l? Invoke special macro
  2794.     jne    atrsm11            ; ne = no
  2795.     cmp    modeset,0        ; resetting?
  2796.     jne    atrsm10a        ; ne = no, setting
  2797.     jmp    vtrmac            ; jump to perform on-line macro
  2798.                     ;  code is located in file msy
  2799. atrsm10a:jmp    vtsmac            ; do set macro
  2800.  
  2801. atrsm11:cmp    al,38            ; 38? Enter Tek sub-mode. VT340 seq
  2802.     jne    atrsm12            ; ne = no
  2803.     cmp    modeset,1        ; setting mode (ESC [ ? 38 h)?
  2804.     jne    atrsm12            ; ne = no, ignore sequence
  2805.     test    denyflg,tekxflg        ; is auto Tek mode disabled?
  2806.     jnz    atrsm12            ; nz = yes, just ignore command
  2807.     call    atsc            ; save cursor and associated data
  2808.     xor    al,al            ; enter with this received character
  2809.     call    TEKEMU            ; go to Tektronix Emulator, al=null
  2810.     jmp    atnorm
  2811.  
  2812. atrsm12:cmp    al,42            ; 42, use NRC 7-bit command?
  2813.     jne    atrsm15            ; ne = no
  2814.     test    flags.vtflg,ttvt320+ttvt220 ; VT320/VT220 mode?
  2815.     jz    atrsm14            ; z = no
  2816.     cmp    vtemu.vtchset,0        ; ASCII?
  2817.     je    atrsm14            ; e = yes, no NRC
  2818.     cmp    vtemu.vtchset,12    ; highest NRC ident?
  2819.     ja    atrsm14            ; a = not NRC
  2820.     cmp    modeset,0        ; resetting?
  2821.     je    atrsm13            ; e = yes
  2822.     or    vtemu.vtflgop,vsnrcm    ; set NRC flag bit
  2823.     jmp    chrdef            ; and set NRC characters
  2824. atrsm13:mov    ax,vtemu.vtflgop    ; run time flags
  2825.     and    vtemu.vtflgop,not vsnrcm ; turn off NRC flag bit
  2826.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls
  2827.     jmp    chrdef
  2828. atrsm14:ret
  2829. atrsm15:cmp    al,66            ; 66, keypad to applications mode?
  2830.     jne    atrsm16            ; ne = no
  2831.     test    flags.vtflg,ttvt320+ttvt220 ; VT320/VT220 mode?
  2832.     jz    atrsm16            ; z = no
  2833.     mov    ax,deckpam        ; bit to control
  2834.     jmp    atrsflg            ; control the flag and return
  2835. atrsm16:ret
  2836.  
  2837. ; VT340  CSI number $ |   number is 0 or 80 for 80 cols, 132 for 132 columns
  2838. ; DECSCPP, set columns per page
  2839. atscpp:    cmp    inter,'$'        ; correct intermediate letter?
  2840.     jne    atscpp2            ; ne = no, ignore
  2841.     cmp    ninter,1        ; one intermediate?
  2842.     jne    atscpp2            ; ne = no, ignore
  2843.     mov    modeset,1        ; assume 132 columns wanted
  2844.     cmp    param,80        ; 80 or 132 columns?
  2845.     ja    atscpp1            ; a = 132 columns
  2846.     mov    modeset,0        ; set to 80 columns
  2847. atscpp1:mov    al,3            ; set up CSI ? 3 h/l command
  2848.     jmp    atrsm6            ; process that command
  2849. atscpp2:ret
  2850.  
  2851.         ; Heath-19  ESC [ > Ps h or l where Ps = 1, 4, 7, or 9
  2852. htrsm1:    cmp    al,1            ; 25th line?
  2853.     jne    htrsm4            ; ne = no
  2854.     and    h19stat,not h19l25    ; clear 25th line bit
  2855.     cmp    modeset,0        ; clearing?
  2856.     je    htrsm1a            ; e = yes
  2857.     or    h19stat,h19l25        ; set bit
  2858.     jmp    htrsmx            ; we are done
  2859. htrsm1a:mov    ah,byte ptr low_rgt+1    ; point to status (25th) line
  2860.     inc    ah            ;  which is here
  2861.     xor    al,al            ; from column 0
  2862.     mov    bh,ah            ; to same line
  2863.     mov    bl,crt_cols        ; physical width
  2864.     dec    bl            ; we count from 0
  2865.     jmp    vtsclr            ; disabling status line clears it
  2866.  
  2867. htrsm4:    cmp    al,4            ; 4, block/line cursor?
  2868.     jne    htrsm5            ; ne = no
  2869.     and    h19ctyp,4        ; save on/off bit (4)
  2870.     cmp    modeset,0        ; reset?
  2871.     je    htrsm4a            ; e = yes
  2872.     or    h19ctyp,2        ; remember block kind here
  2873.     jmp    atsctyp
  2874. htrsm4a:or    h19ctyp,1        ; remember underline kind here
  2875.     jmp    atsctyp
  2876.      
  2877. htrsm5: cmp     al,5                    ; 5, on/off cursor?
  2878.         jne     htrsm7                  ; ne = no
  2879.         cmp     modeset,0               ; on?
  2880.         je      htrsm5a                 ; e = yes
  2881.     or    h19ctyp,4        ; remember off state in this bit
  2882.         jmp     atsctyp
  2883. htrsm5a:and    h19ctyp,not 4        ; set cursor on
  2884.         jmp     atsctyp
  2885.  
  2886. htrsm7:    cmp    al,7            ; 7, alternate application keypad?
  2887.     jne    htrsm8            ; ne = no
  2888.     mov    ax,deckpam        ; get keypad application mode bit
  2889.     jmp    atrsflg            ; set or reset appl keypad mode
  2890.  
  2891. htrsm8:    cmp    al,8            ; 8, received CR => CR/LF?
  2892.     jne    htrsm9
  2893.     and    h19stat,not h19alf    ; clear autoline feed bit
  2894.     cmp    modeset,0        ; resetting?
  2895.     je    htrsmx            ; yes
  2896.     or    h19stat,h19alf        ; turn on the mode
  2897.     ret
  2898.  
  2899. htrsm9:    cmp    al,9            ; 9, auto newline mode? (add cr to lf)
  2900.     jne    htrsmx            ; ne = no
  2901.     mov    ax,anslnm        ; get the bit
  2902.     jmp    atrsflg            ; set or reset newline mode
  2903. htrsmx:    ret                ; ignore the code
  2904.  
  2905. atrsflg:cmp    modeset,0        ; reset?
  2906.     je    atrsf1            ; e = yes, reset it
  2907.     or    vtemu.vtflgop,ax    ; set, OR in the flag
  2908.     test    ax,decanm        ; changing ansi mode?
  2909.     jz    atrsfx            ; z = no
  2910.     cmp    flags.vtflg,ttheath    ; in Heath-19 mode?
  2911.     je    atrsfx            ; e = yes, don't flip terminal kinds
  2912.     mov    al,oldterm        ; terminal type at startup
  2913.     mov    flags.vtflg,al        ; restore it
  2914.     ret
  2915. atrsf1: not    ax            ; reset bit, complement
  2916.     and    vtemu.vtflgop,ax    ; clear the bit
  2917.     not    ax            ; recover the bit
  2918.     test    ax,decanm        ; changing ansi mode?
  2919.     jz    atrsfx            ; z = no
  2920.     cmp    flags.vtflg,ttheath    ; in Heath-19 mode?
  2921.     je    atrsfx            ; e = yes, don't flip terminal kinds
  2922.     mov    flags.vtflg,ttvt52    ; say VT52 now
  2923. atrsfx:    ret
  2924.                     ; Set/Clear Origin mode
  2925. atrsom:    test    dspstate,dsptype    ; on status line?
  2926.     jz    atrsom1            ; z = no
  2927.     ret                ; else ignore this command
  2928. atrsom1:cmp    modeset,0        ; clearing DEC origin mode?
  2929.     jne    atrsom2            ; ne = no, setting
  2930.     and    vtemu.vtflgop,not decom ; reset Origin mode
  2931.     xor    dx,dx            ; go to the home position
  2932.     jmp    atscu5            ; set cursor and return
  2933. atrsom2:or    vtemu.vtflgop,decom    ; set Origin mode
  2934.     mov    dx,cursor        ; get the cursor
  2935.     xor    dl,dl            ; go to right margin
  2936.     mov    dh,mar_top        ; go to home of scrolling region
  2937.     jmp    atscu5            ; set the cursor and return
  2938.  
  2939. atrsscnm:cmp    modeset,0        ; resetting?
  2940.     je    atrss1            ; e = yes, reset
  2941.     test    vtemu.vtflgop,vsscreen    ; setting, set already?
  2942.     jnz    atrss3            ; nz = yes, don't do it again
  2943.     or    vtemu.vtflgop,vsscreen    ; set and tell Status display
  2944.     jmp    short atrss2        ; do it
  2945.  
  2946. atrss1: test    vtemu.vtflgop,vsscreen    ; resetting, reset already?
  2947.     jz    atrss3            ; z = yes, don't do it again
  2948.     and    vtemu.vtflgop,not vsscreen ; clear and tell Status
  2949.                     ; fall through to atrss2
  2950.  
  2951. ; Note: This is also called from the stblmds initialization routine.
  2952. ; Reverse video the entire screen, update scbattr and curattr to match.
  2953. atrss2:    push    ax
  2954.     mov    ah,scbattr        ; current screen attributes
  2955.     call    revideo            ; reverse them
  2956.     mov    scbattr,ah        ; set screen background attribute
  2957.     mov    ah,curattr        ; get current cursor attribute
  2958.     call    revideo            ; reverse it
  2959.     mov    curattr,ah        ; store it
  2960.     pop    ax
  2961.     call    revscn            ; reverse everything on the screen
  2962. atrss3: ret
  2963.  
  2964.                     ; Self tests DECTST
  2965. atctst:    cmp    inter,0            ; any intermediate char?
  2966.     jne    atcts3            ; ne = yes, not a selftest command
  2967.     cmp    param,2            ; VT102 selftest?
  2968.     je    atcts1            ; e = yes
  2969.     cmp    param,4            ; VT320 selftest?
  2970.     jne    atcts6            ; ne = no
  2971. atcts1:    test    dspstate,dsptype    ; cursor is on status line?
  2972.     jz    atcts2            ; z = no
  2973.     push    param            ; save first parameter
  2974.     mov    ah,inter        ;  and first intermediate char
  2975.     push    ax
  2976.     mov    param,0            ; select main display
  2977.     mov    inter,'$'        ; setup proper intermediate
  2978.     call    atssdt            ; select status line of off
  2979.     call    atsasd            ; select main display
  2980.     pop    ax
  2981.     pop    param            ; restore parameter
  2982.     mov    inter,ah        ;  and intermediate char
  2983. atcts2:    xor    al,al            ; init test weight
  2984.     mov    di,offset atcts4    ; routine to call
  2985.     call    atreps            ; repeat for all parms
  2986.     test    al,80H            ; reset?
  2987.     jz    atcts3            ; z = no, return
  2988.     jmp    atreset            ; reset everything
  2989. atcts3: ret
  2990.  
  2991. atcts4:    or    si,si            ; initial arg?
  2992.     jz    atcts5            ; z = yes, skip it (examined above)
  2993.     cmp    param[si],1        ; power up test (0, 1) included?
  2994.     ja    atcts5            ; a = no, ignore printer/comms/repeats
  2995.     or    al,80H            ; say we want reset
  2996. atcts5: ret
  2997.  
  2998. atcts6:    cmp    nparam,0        ; absence of parameters?
  2999.      jne    atcts5            ; ne = no, ignore sequence
  3000.     jmp    athoney            ; try Honeywell ESC [ y  ident response
  3001.  
  3002. atalign    proc    near            ; Align screen, fill screen with 'E's
  3003.     test    dspstate,dsptype    ; is cursor on status line?
  3004.     jz    atalig1            ; z = no
  3005.     ret                ; yes, ignore the command
  3006. atalig1:cmp    flags.modflg,0        ; is mode line off?
  3007.     je    atalig2            ; e = yes
  3008.     and    yflags,not modoff    ; say it's on
  3009.     mov    flags.modflg,1        ;  and owned by us
  3010. atalig2:call    atreset            ; clear system
  3011.     or    vtemu.vtflgop,decawm    ; set wrap
  3012.     mov    cl,byte ptr low_rgt    ; number of columns-1
  3013.     inc    cl
  3014.     mov    al,byte ptr low_rgt+1    ; number of rows-1
  3015.     inc    al
  3016.     mul    cl            ; ax = number of chars on screen
  3017.     mov    cx,ax
  3018. atalig3:push    cx
  3019.     mov    al,'E'            ; write screen full of E's
  3020.     call    atnrm            ; write the 'E'
  3021.     pop    cx
  3022.     loop    atalig3            ; cx times
  3023.     ret
  3024. atalign    endp
  3025.  
  3026.  
  3027. ; Reports
  3028. atreqt: cmp    param,1            ; want report?
  3029.     jbe    atreq1            ; be = yes
  3030. atreq0:    ret                ; Gee, must have been an echo
  3031.  
  3032. atreq1:    test    flags.vtflg,ttvt102+ttvt100+tthoney ; VT102 etc?
  3033.     jz    atreq0            ; z = no, ignore
  3034.     mov    ttyact,0        ; group output for networks
  3035.     mov    al,CSI
  3036.     call    prtbout            ; send CSI or ESC [
  3037.     mov    al,'3'            ; we report only upon request
  3038.     cmp    param,0            ; was argument a zero?
  3039.     jne    atreq1b            ; ne = no
  3040.     mov    al,'2'            ; yes
  3041. atreq1b:call    prtbout
  3042.     mov    al,';'            ; separate
  3043.     call    prtbout
  3044.     mov    bl,parcode        ; get the parity code
  3045.     xor    bh,bh
  3046.     mov    al,partab[bx]        ; get VT100 parity code
  3047.     push    ax            ; save parity code
  3048.     call    prtnout            ; send number to the port
  3049.     mov    al,';'            ; separate
  3050.     call    prtbout
  3051.     mov    al,'2'            ; assume 7 data bits
  3052.     pop    bx            ; get parity code into bl
  3053.     cmp    bl,1            ; is parity none?
  3054.     jne    atreq2            ; ne = no, so 7 data bits
  3055.     test    flags.remflg,d8bit    ; 8 bit display?
  3056.     jz    atreq2            ; z = no
  3057.     mov    al,'1'            ; must be eight
  3058. atreq2: call    prtbout            ; send it to the port
  3059.     mov    al,';'
  3060.     call    prtbout
  3061.     mov    bl,baudidx        ; baud rate index
  3062.     xor    bh,bh
  3063.     mov    al,baudtab[bx]        ; get DEC baud rate code
  3064.     push    ax
  3065.     call    prtnout            ; sending speed index
  3066.     mov    al,';'
  3067.     call    prtbout
  3068.     pop    ax
  3069.     cmp    bl,lbaudtab-1        ; using the split speed entry?
  3070.     jne    atreq2a            ; ne = no
  3071.     mov    al,[bx+1]        ; get trailing receive speed (75 baud)
  3072. atreq2a:call    prtnout            ; receiving speed index
  3073.     mov    al,';'
  3074.     call    prtbout
  3075.     mov    al,'1'            ; clock rate multiplier is always 1
  3076.     call    prtbout
  3077.     mov    al,';'
  3078.     call    prtbout
  3079.     mov    al,'0'            ; Flags are always zero (no STP)
  3080.     call    prtbout
  3081.     mov    ttyact,1        ; end group output for networks
  3082.     mov    al,'x'
  3083.     call    prtbout
  3084.     ret
  3085.  
  3086.                     ; Single Controls
  3087. ; Note DEC manual incorrectly says DECSCL's do a hard rather than soft reset
  3088. decscl:    cmp    inter,'!'        ; "CSI ! p" soft reset?
  3089.     jne    decsc0            ; ne = no
  3090.     jmp    atsres            ; do a soft reset
  3091.  
  3092. decsc0:    cmp    inter,'"'        ; "CSI Psc; Ps1 " p"  operating level?
  3093.     je    decsc1            ; e = yes
  3094.     cmp    inter,'$'        ; "CSI Pn $ p"  DECRQM?
  3095.     jne    decsc0a            ; ne = no, ignore others
  3096.     jmp    decsc5            ; do isolated controls report
  3097. decsc0a:ret                ; else ignore
  3098. decsc1:    cmp    param,61        ; Psc, select VT100?
  3099.     jne    decsc2            ; ne = no
  3100.     mov    flags.vtflg,ttvt102    ; set VT102
  3101.     mov    oldterm,ttvt102        ; and remember it
  3102.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls
  3103.     mov    al,anspflg        ; preserve screen print flag
  3104.     push    ax
  3105.     call    atsres            ; do soft reset of emulator
  3106.     pop    ax
  3107.     mov    anspflg,al
  3108.     ret
  3109. decsc2:    cmp    param,62        ; go to VT2xx level?
  3110.     jne    decsc3            ; ne = no
  3111.     test    flags.vtflg,ttvt320+ttvt102 ; at VT300/VT102 level now?
  3112.     jnz    decsc3a            ; nz = yes, don't change types
  3113.     mov    flags.vtflg,ttvt220    ; set VT220 mode
  3114.     mov    oldterm,ttvt220
  3115.     jmp    short decsc3b        ; finish up
  3116.     
  3117. decsc3:    cmp    param,63        ; go to VT300 level?
  3118.     jne    decsc4            ; ne = no
  3119. decsc3a:mov    flags.vtflg,ttvt320    ; set VT320 mode
  3120.     mov    oldterm,ttvt320
  3121. decsc3b:cmp    param[2],2        ; Ps1, range here is 0, 1, 2
  3122.     ja    decsc4            ; a = out of range, ignore
  3123.     mov    al,anspflg        ; preserve screen print flag
  3124.     push    ax
  3125.     call    atsres            ; do soft reset of emulator
  3126.     pop    ax
  3127.     mov    anspflg,al
  3128.     and    vtemu.vtflgop,not vscntl ; turn off 8-bit controls
  3129.     cmp    param[2],1        ; select 7-bit controls?
  3130.     je    decsc4            ; e = yes, we have done so
  3131.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls
  3132. decsc4:    ret
  3133.                            ; single controls report request
  3134. decsc5:    cmp    lparam,'?'        ; want DEC Private modes?
  3135.     jne    decsc5a            ; ne = no
  3136.     call    decscpre        ; do standard prefix
  3137.     mov    al,'2'            ; assume mode is reset
  3138.     call    decsc20            ; do DEC Private mode report
  3139.     jmp    decscend        ; do end of sequence
  3140. decsc5a:cmp    inter,0            ; intermediate char?
  3141.     je    decsc5b            ; e = no, ignore
  3142.     call    decscpre        ; do standard prefix
  3143.     mov    al,'2'            ; assume mode is reset
  3144.     call    decsc5c            ; do ANSI report
  3145.     jmp    decscend        ; do end of sequence
  3146. decsc5b:ret                ; else return failure
  3147.                     
  3148. decsc5c:mov    cx,param        ; ANSI report:
  3149.     cmp    cx,2            ; 2, Keyboard action?
  3150.     jne    decsc6            ; ne = no
  3151.     ret
  3152. decsc6:    cmp    cx,3            ; control representation?
  3153.     jne    decsc7            ; ne = no
  3154.     ret                ; say reset(acting on controls)
  3155. decsc7:    cmp    cx,4            ; 4, Insert/Replace mode?
  3156.     jne    decsc8            ; ne = no
  3157.     cmp    insmod,0        ; insert mode off?
  3158.     je    decsc7a            ; e = yes, off
  3159.     dec    al            ; say is on
  3160. decsc7a:ret
  3161. decsc8:    cmp    cx,10            ; 10, Horizontal editing?
  3162.     jne    decsc9            ; ne = no
  3163.     mov    al,'4'            ; permanently reset
  3164.     ret
  3165. decsc9:    cmp    cx,12            ; 12, Send/Receive (local echo)?
  3166.     jne    decsc11            ; ne = no
  3167.     test    vtemu.vtflgop,dececho    ; set?
  3168.     jz    decsc12            ; z = no
  3169.     dec    al            ; say set
  3170.     ret
  3171. decsc11:cmp    cx,20            ; 20, new line mode?
  3172.     jne    decsc13            ; ne = no
  3173.     test    vtemu.vtflgop,anslnm    ; new line set?
  3174.     jz    decsc12            ; z = no, reset
  3175.     dec    al            ; say set
  3176. decsc12:ret
  3177. decsc13:mov    al,'0'            ; say not recognized
  3178.     ret
  3179.  
  3180.                            ; DEC Private mode report
  3181. decsc20:mov    cx,param
  3182.     cmp    cx,1            ; 1, cursor keys?
  3183.     jne    decsc22            ; ne = no
  3184.     test    vtemu.vtflgop,decckm    ; set?
  3185.     jz    decsc31            ; z = no, reset
  3186.     dec    al
  3187.     ret
  3188. decsc22:cmp    cx,2            ; 2, ANSI mode
  3189.     jne    decsc24            ; ne = no
  3190.     test    vtemu.vtflgop,decanm    ; set?
  3191.     jz    decsc31            ; z = no, reset
  3192.     dec    al
  3193.     ret
  3194. decsc24:cmp    cx,3            ; 3, column
  3195.     jne    decsc26            ; ne = no
  3196.     test    vtemu.vtflgop,deccol    ; 132 column mode set?
  3197.     jz    decsc31            ; z = no, reset (80 columns)
  3198.     dec    al
  3199.     ret
  3200. decsc26:cmp    cx,4            ; 4, scrolling mode
  3201.     je    decsc31            ; e = yes always say reset (jump)
  3202.                     ;
  3203.     cmp    cx,5            ; 5, screen
  3204.     jne    decsc28            ; ne = no
  3205.     test    vtemu.vtflgop,decscnm    ; set (light background)?
  3206.     jz    decsc31            ; z = no, reset
  3207.     dec    al
  3208.     ret
  3209. decsc28:cmp    cx,6            ; 6, Origin mode?
  3210.     jne    decsc30            ; ne = no
  3211.     test    dspstate,dsptype    ; on status line?
  3212.     jz    decsc29            ; z = no, main display
  3213.     test    dspstate,dspdecom    ; main display Origin mode set?
  3214.     jz    decsc31            ; z = no, reset
  3215.     dec    al
  3216.     ret
  3217. decsc29:test    vtemu.vtflgop,decom    ; Origin mode set?
  3218.     jz    decsc31            ; z = no, reset
  3219.     dec    al
  3220.     ret
  3221. decsc30:cmp    cx,7            ; 7, autowrap?
  3222.     jne    decsc32            ; ne = no
  3223.     test    vtemu.vtflgop,decawm    ; set?
  3224.     jz    decsc31            ; z = no, reset
  3225.     dec    al
  3226. decsc31:ret                ; common return point
  3227. decsc32:cmp    cx,8            ; 8, autorepeat?
  3228.     jne    decsc34            ; ne = no
  3229.     dec    al
  3230.     ret                ; say set
  3231. decsc34:cmp    cx,18            ; 18, print Form Feed?
  3232.     jne    decsc36            ; ne = no
  3233.     test    anspflg,vtffp        ; set?
  3234.     jz    decsc31            ; z = no, reset
  3235.     dec    al
  3236.     ret
  3237. decsc36:cmp    cx,19            ; 19, printer extent?
  3238.     jne    decsc38            ; ne = no
  3239.     test    anspflg,vtextp        ; set?
  3240.     jz    decsc31            ; z = no, reset
  3241.     dec    al
  3242.     ret
  3243. decsc38:cmp    cx,25            ; 25, text cursor enabled?
  3244.     jne    decsc40            ; ne = no
  3245.     test    atctype,4        ; 4 is off
  3246.     jnz    decsc31            ; nz = off/disabled
  3247.     dec    al            ; say enabled
  3248.     ret
  3249. decsc40:cmp    cx,42            ; 42, NRC's
  3250.     jne    decsc42            ; ne = no
  3251.     test    flags.vtflg,ttvt320+ttvt220 ; VT320/VT220?
  3252.     jz    decsc31            ; z = no
  3253.     test    vtemu.vtflgop,vsnrcm    ; NRC's active?
  3254.     jz    decsc31            ; z = no
  3255.     dec    al            ; say enabled
  3256.     ret
  3257. decsc42:cmp    cx,66            ; 66, numeric keypad?
  3258.     jne    decsc44            ; ne = no
  3259.     test    vtemu.vtflgop,deckpam    ; set?
  3260.     jz    decsc31            ; z = no, reset
  3261.     dec    al            ; say set
  3262.     ret
  3263. decsc44:cmp    cx,68            ; 68, keyboard usage?
  3264.     jne    decsc45            ; ne = no
  3265.     mov    al,'4'            ; say always typewriter mode
  3266.     ret
  3267. decsc45:mov    al,'0'            ; say unknown kind
  3268.     ret
  3269.  
  3270. decscpre:mov    ttyact,0        ; group output for networks
  3271.     mov    al,CSI            ; do standard report beginning
  3272.     call    prtbout
  3273.     mov    al,byte ptr param    ; get parameter
  3274.     call    prtnout            ; send the number
  3275.     mov    al,';'
  3276.     call    prtbout
  3277.     ret
  3278.  
  3279. decscend:call    prtbout            ; do standard rpt end, send char in al
  3280.     mov    al,'$'
  3281.     call    prtbout
  3282.     mov    ttyact,1        ; end group output for networks
  3283.     mov    al,'y'
  3284.     call    prtbout
  3285.     ret
  3286.  
  3287. ; DEC style Soft Reset
  3288. ; Note: graphics rendition is NOT changed by soft reset, DEC manual is wrong.
  3289. atsres    proc    near            ; do soft reset of terminal
  3290.     test    dspstate,dsptype    ; on status line?
  3291.     jz    atsres1            ; z = no, on main display
  3292.     mov    param,0
  3293.     mov    inter,'$'        ; setup entry for atsasd
  3294.     call    atsasd            ; select main display
  3295. atsres1:and    vtemu.vtflgop,not(decawm+decckm+deckpam+decom) ; these go off
  3296.     mov    insmod,0        ; insert mode off
  3297.     mov    mar_top,0        ; reset scrolling margins
  3298.     mov    al,byte ptr low_rgt+1
  3299.     mov    mar_bot,al        ; to full screen
  3300.     mov    anspflg,0        ; clear printer flag
  3301.     mov    al,1            ; restore cursor, assume underline (1)
  3302.     test    vtemu.vtflgop,vscursor    ; underline?
  3303.     jnz    atsres2            ; nz = yes
  3304.     inc    al            ; block (2)
  3305. atsres2:mov    atctype,al        ; save VTxxx cursor type here
  3306.     call    atsctyp            ; set the cursor type
  3307.     push    cursor
  3308.     mov    cursor,0        ; set save cursor to Home
  3309.     call    atsc            ; save attributes
  3310.     pop    cursor            ; restore active cursor
  3311.     call    chrdef            ; set default character set
  3312.     jmp    ansdsl            ; update status line
  3313. atsres    endp
  3314.                     ; DECRQSS/DECRPSS Control Settings
  3315.  
  3316.                     ; Handle DCS ... q string ST
  3317. atcrq:    cmp    ninter,1        ; one intermediate?
  3318.     je    atcrq1            ; e = yes
  3319.     ja    atcrq0            ; a = too many
  3320.     jmp    atcrqq            ; none, do Sixel DCS params q...ST
  3321. atcrq0:    mov    ninter,0        ; set up atdcsnul for proper form
  3322.     mov    ttstate,offset atdcsnul    ; not understood, consume til ST
  3323.     ret
  3324.  
  3325. atcrq1:    cmp    inter,'$'        ; correct intermediate?
  3326.     jne    atcrq0            ; ne = no
  3327.     cmp    nparam,0        ; and no parameters?
  3328.     jne    atcrq0            ; ne = have some, not ours
  3329.     mov    ttstateST,offset atcrq4    ; set state for ST arrival
  3330.     mov    ttstate,offset atcrq2    ; next state gets string contents
  3331.     mov    emubufc,0        ; clear buffer counter
  3332.     mov    word ptr emubuf,0    ; empty start of buffer
  3333.     ret
  3334. atcrq2:    mov    bx,emubufc        ; count of chars in string buffer
  3335.     cmp    bx,emubufl        ; too many?
  3336.     jae    atcrq3            ; ae = too many, ignore extras
  3337.     mov    emubuf[bx],al        ; store the char
  3338.     inc    emubufc            ; count it
  3339. atcrq3:    ret
  3340.                     ; here after ST has been seen
  3341. atcrq4:    cmp    emubufc,2        ; max string chars we want
  3342.     jbe    atcrq4a            ; be = ok
  3343.     jmp    atnorm            ; a = too many, ignore
  3344. atcrq4a:mov    ax,word ptr emubuf    ; get first two chars
  3345.     cmp    ax,'}$'            ; select active display?
  3346.     jne    atcrq5            ; ne = no
  3347.     jmp    atcrqd            ; do the routine
  3348. atcrq5:    cmp    ax,'p"'            ; set conformance level?
  3349.     jne    atcrq7            ; ne = no
  3350.     jmp    atcrqp
  3351. atcrq7:    cmp    ax,'~$'            ; set status line type
  3352.     jne    atcrq8
  3353.     jmp    atcrqt
  3354. atcrq8:    cmp    ax,'r'            ; set top and bottom margins?
  3355.     jne    atcrq9
  3356.     jmp    atcrqr
  3357. atcrq9:    cmp    ax,'m'            ; set graphic rendition?
  3358.     jne    atcrq10
  3359.     jmp    atcrqm
  3360. atcrq10:jmp    atcrqxx            ; unknown command
  3361.                     ; DCS $ q  response routines
  3362. atcrqr:    call    atcrqbeg        ; 'r', top/bottom margins
  3363.     test    dspstate,dsptype    ; doing status line display?
  3364.     jz    atcrqr2            ; z = no
  3365.     mov    al,byte ptr dspmsave    ; get saved top margin
  3366.     inc    al
  3367.     call    prtnout
  3368.     mov    al,';'
  3369.     call    prtbout
  3370.     mov    al,byte ptr dspmsave+1    ; get saved bottom margin
  3371.     jmp    short atcrqr3        ; finish up
  3372. atcrqr2:mov    al,mar_top        ; top margin
  3373.     inc    al            ; move to 1,1 system
  3374.     call    prtnout
  3375.     mov    al,';'
  3376.     call    prtbout
  3377.     mov    al,mar_bot
  3378. atcrqr3:inc    al            ; move to 1,1 system
  3379.     call    prtnout
  3380.     mov    al,'r'            ; final char
  3381.     jmp    atcrqend        ; do epilogue
  3382.  
  3383. atcrqm:    call    atcrqbeg        ; 'm', graphics rendition
  3384.     mov    al,'0'            ; say start with all attributes off
  3385.     call    prtbout
  3386.     mov    ah,scbattr        ; current attribute
  3387.     call    getbold            ; returns ah with bold attr or 0
  3388.     or    ah,ah            ; bold set?
  3389.     je    atcrqm2            ; e = no
  3390.     mov    al,';'
  3391.     call    prtbout
  3392.     mov    al,'1'            ; say bold is on
  3393.     call    prtbout
  3394. atcrqm2:mov    ah,scbattr
  3395.     call    getunder        ; underline
  3396.     or    ah,ah            ; underline on?
  3397.     je    atcrqm3            ; e = no, do next
  3398.     mov    al,';'
  3399.     call    prtbout
  3400.     mov    al,'4'            ; say underlining is on
  3401.     call    prtbout
  3402. atcrqm3:mov    ah,scbattr
  3403.     call    getblink        ; blinking
  3404.     or    ah,ah            ; blinking on?
  3405.     je    atcrqm4            ; e = no
  3406.     mov    al,';'
  3407.     call    prtbout
  3408.     mov    al,'5'            ; say blinking is on
  3409.     call    prtbout
  3410. atcrqm4:cmp    video_state,0        ; chars in reversed video?
  3411.     je    atcrqm5            ; e = no
  3412.     mov    al,';'
  3413.     call    prtbout
  3414.     mov    al,'7'            ; say underlining is on
  3415.     call    prtbout
  3416. atcrqm5:mov    al,'m'            ; final char
  3417.     jmp    atcrqend        ; do epilogue
  3418.  
  3419. atcrqd:    call    atcrqbeg        ; '$}', writing to screen/status line
  3420.     mov    al,'0'            ; assume writing to main display
  3421.     test    dspstate,dsptype    ; get type of display
  3422.     jz    atcrqd2            ; z = main display
  3423.     inc    al            ; say writing to mode line
  3424. atcrqd2:call    prtbout
  3425.     mov    al,'$'            ; final chars
  3426.     call    prtbout
  3427.     mov    al,7dh            ; right curly brace
  3428.     jmp    atcrqend        ; do epilogue
  3429.  
  3430. atcrqt:    call    atcrqbeg        ; '$~', status line
  3431.     mov    al,'0'            ; assume mode line is off
  3432.     test    yflags,modoff        ; is mode line off?
  3433.     jnz    atcrqt2            ; nz = yes
  3434.     mov    al,'2'            ; mode line is on and host writable
  3435. atcrqt2:call    prtbout
  3436.     mov    al,'c'            ; final chars
  3437.     call    prtbout
  3438.     mov    al,7eh            ; tilde
  3439.     jmp    atcrqend        ; do epilogue
  3440.                     ; '"p' set conformance level
  3441. atcrqp:    cmp    oldterm,ttvt100        ; main-mode terminal is VT100?
  3442.     je    atcrqp2            ; e = yes
  3443.     cmp    oldterm,tthoney        ; Honeywell?
  3444.     je    atcrqp2            ; e = yes
  3445.     cmp    oldterm,ttvt102        ; VT102?
  3446.     je    atcrqp2            ; e = yes
  3447.     cmp    oldterm,ttvt320        ; how about VT320?
  3448.     je    atcrqp2            ; e = yes
  3449.     jmp    atcrqxx            ; say invalid request
  3450. atcrqp2:mov    ttyact,0        ; group output for networks
  3451.     mov    al,DCS            ; '"p', conformance level
  3452.     call    prtbout
  3453.     mov    al,'0'            ; valid request
  3454.     call    prtbout
  3455.     mov    al,'$'
  3456.     call    prtbout
  3457.     mov    al,61            ; assume VT102
  3458.     cmp    oldterm,ttvt100        ; VT100?
  3459.     je    atcrqp2a        ; e = yes
  3460.     cmp    oldterm,tthoney        ; Honeywell
  3461.     je    atcrqp2a        ; e = yes
  3462.     cmp    oldterm,ttvt102        ; are we a VT102?
  3463.     jne    atcrqp3            ; ne = no
  3464. atcrqp2a:call    prtnout
  3465.     jmp    short atcrqp5        ; finish the report
  3466.  
  3467. atcrqp3:mov    al,63            ; say VT320
  3468.     call    prtnout
  3469.     mov    al,';'
  3470.     call    prtbout
  3471.     mov    al,'2'            ; assume 8-bit controls are on
  3472.     test    vtemu.vtflgop,vscntl    ; 8-bit controls active?
  3473.     jnz    atcrqp4            ; nz = yes
  3474.     mov    al,'1'            ; else say only 7-bit controls
  3475. atcrqp4:call    prtbout
  3476. atcrqp5:mov    al,'"'            ; final characters
  3477.     call    prtbout
  3478.     mov    al,'p'
  3479.     jmp    atcrqend        ; do epilogue
  3480.  
  3481. atcrqbeg:mov    ttyact,0        ; group output for networks
  3482.     mov    al,DCS            ; report prologue
  3483.     call    prtbout
  3484.     mov    al,'0'            ; valid request
  3485.     call    prtbout
  3486.     mov    al,'$'
  3487.     jmp    prtbout
  3488.  
  3489. atcrqend:call    prtbout            ; report epilogue, al has char
  3490.     mov    ttyact,1        ; end group output for networks
  3491.     mov    al,STCHR        ; string terminator
  3492.     jmp    prtbout
  3493.  
  3494. atcrqxx:mov    ttyact,0        ; group output for networks
  3495.     mov    al,DCS            ; report invalid request
  3496.     call    prtbout
  3497.     mov    al,'1'            ; invalid request
  3498.     call    prtbout
  3499.     mov    al,'$'
  3500.     cmp    emubufc,1        ; any first char?
  3501.     jb    atcrqend        ; b = no
  3502.     call    prtbout
  3503.     mov    al,emubuf        ; first string char
  3504.     cmp    emubufc,2        ; two string chars?
  3505.     jne    atcrqend        ; ne = no
  3506.     call    prtbout
  3507.     mov    al,emubuf+1        ; second string char
  3508.     jmp    atcrqend        ; do epilogue
  3509.  
  3510.                     ; DCS P1; P2; P3 <char> Sixel command
  3511. atcrqq:    cmp    dcsstrf,'q'        ; final char of 'q'? Sixel draw
  3512.     je    atcrqq1            ; e = yes
  3513.     cmp    dcsstrf,'p'        ; 'p', restore palette?
  3514.     jne    atcrqq0            ; ne = no
  3515.     cmp    dinter,'$'        ; DCS 2 $ p?
  3516.     jne    atcrqq0            ; ne = no
  3517.     cmp    param,2            ; this too?
  3518.     jne    atcrqq1            ; ne = no
  3519.     call    tekinq            ; get Tek screen state
  3520.     jmp    tekrcol            ; restore palette
  3521.  
  3522. atcrqq0:mov    ninter,0        ; setup atdcsnul for proper form
  3523.     jmp    atdcsnul        ; consume unknown command
  3524. atcrqq1:test    denyflg,tekxflg        ; is auto Tek mode disabled?
  3525.     jnz    atcrqq0            ; nz = yes, consume
  3526.     mov    di,offset emubuf    ; temp buffer
  3527.     mov    byte ptr [di],escape    ; do ESC ^L to erase screen
  3528.     inc    di
  3529.     mov    byte ptr [di],FF
  3530.     inc    di
  3531.     mov    byte ptr [di],escape    ; start DCS
  3532.     inc    di
  3533.     mov    byte ptr [di],'P'
  3534.     inc    di
  3535.     mov    ax,dparam[0]        ; get first parameter
  3536.     call    dec2di
  3537.     mov    byte ptr [di],';'
  3538.     inc    di
  3539.     mov    ax,dparam[2]        ; get second parameter
  3540.     call    dec2di            ; write ascii value
  3541.     mov    byte ptr [di],';'
  3542.     inc    di
  3543.     mov    ax,dparam[4]        ; get third parameter
  3544.     call    dec2di            ; write ascii value
  3545.     mov    al,dcsstrf
  3546.     mov    byte ptr [di],al    ; final char
  3547.     mov    byte ptr [di+1],0    ; terminator
  3548.     mov    di,offset emubuf
  3549.     mov    al,yflags        ; get yflags
  3550.     and    al,capt            ; save logging bit
  3551.     push    ax
  3552.     and    yflags,not capt        ; turn off logging bit
  3553. atcrqq2:mov    al,[di]
  3554.     inc    di
  3555.     or    al,al            ; at the end?
  3556.     jz    atcrqq3            ; z = yes
  3557.     push    di
  3558.     call    tekemu            ; feed Tek emulator this string
  3559.     pop    di
  3560.     jmp    short atcrqq2        ; do another string member
  3561. atcrqq3:mov    chcontrol,1        ; turn on full cell char writing
  3562.     pop    ax            ; recover logging bit
  3563.     or    yflags,al        ; restate logging bit
  3564.     jmp    atnorm
  3565.  
  3566. ; State machine to process DCS strings of type "p" (restore color palette)
  3567. ; Enter with "p" char in AL.
  3568. tekrcol    proc    near
  3569.     mov    ttstate,offset tekrco1    ; next state is get parameter
  3570.     mov    ttstateST,offset tekrcost ; go here on ST
  3571.     push    es
  3572.     push    ds
  3573.     pop    es
  3574.     mov    cx,5            ; five words
  3575.     xor    ax,ax
  3576.     mov    di,offset param        ; clear parameters Pc,Pu,Px,Py,Pz
  3577.     cld
  3578.     rep    stosw
  3579.     pop    es
  3580.     mov    nparam,0        ; work on initial parameter first
  3581.     ret
  3582. tekrco1:push    bx
  3583.     mov    bx,nparam        ; parameter number
  3584.     shl    bx,1            ; make it a word index
  3585.     mov    cx,param[bx]        ; accumulated parameter
  3586.     call    getdec            ; accumulate decimal value
  3587.     mov    param[bx],cx        ; remember accumulation
  3588.     pop    bx
  3589.     jnc    tekrcos1        ; nc = got a digit char
  3590.     inc    nparam            ; say have another complete parameter
  3591.     cmp    al,'/'            ; this kind of separator?
  3592.     je    tekrco3            ; e = yes, finish
  3593.     cmp    al,';'            ; break char is separator?
  3594.     jne    tekrco4            ; ne = no, decode current sequence
  3595. tekrco3:cmp    nparam,5        ; have 5 params already?
  3596.     jb    tekrcos1        ; n = no, continue reading
  3597. tekrco4:call    tekrpal            ; process parameters in msgibm file
  3598.     jmp    tekrcol            ; start over on next field
  3599.  
  3600. tekrcost:mov    ttstate,offset atnrm    ; get here on ST
  3601.     mov    ttstateST,offset atnorm ; default ST completion state
  3602.     cmp    nparam,5        ; enough parameters to finish cmd?
  3603.     jb    tekrcos1        ; b = no, abandon it
  3604.     call    tekrpal            ; update from last data item
  3605. tekrcos1:ret
  3606. tekrcol    endp
  3607.  
  3608. ; Accumulate decimal value in CX using ascii char in al.
  3609. ; Return with value in CX. Return carry clear if ended on a digit,
  3610. ; return carry set and ascii char in al if ended on a non-digit.
  3611. getdec    proc    near
  3612.     cmp    al,'0'            ; a number?
  3613.     jb    getdecx            ; b = no, quit
  3614.     cmp    al,'9'
  3615.     ja    getdecx            ; a = not a number, quit
  3616.     sub    al,'0'            ; remove ascii bias
  3617.     xchg    cx,ax            ; put char in cx, decimal value in ax
  3618.     push    dx            ; save reg
  3619.     mul    ten            ; times ten for a new digit
  3620.     pop    dx            ; recover reg, ignore overflow
  3621.     add    al,cl            ; add current digit
  3622.     adc    ah,0            ; 16 bits worth
  3623.     xchg    ax,cx            ; rpt cnt back to cx
  3624.     clc                ; say found a digit
  3625.     ret
  3626. getdecx:stc                ; say non-digit (in al)
  3627.     ret
  3628. getdec    endp
  3629.                     ; Device Status Reports
  3630. atdsr:    mov    di,offset atdsr1    ; routine to call
  3631.     call    atreps            ; do for all parms
  3632.     ret
  3633.                     ; DSR workers
  3634. atdsr1:    cmp    lparam,0        ; any intermediate?
  3635.     jne    atdsr2            ; ne = yes, an intermediate
  3636.     mov    ax,param[si]
  3637.     cmp    ax,5            ; operating status report?
  3638.     je    rpstat            ; e = yes
  3639.     cmp    ax,6            ; cursor position report?
  3640.     je    rpcup            ; e = yes
  3641.     ret
  3642. atdsr2:    cmp    lparam,'?'        ; DEC mode queries for below?
  3643.     jne    atdsr3            ; no, skip them
  3644.     cmp    ax,6            ; VT340 cursor report?
  3645.     je    rpcup            ; e = yes
  3646.     cmp    ax,15            ; printer status report?
  3647.     je    rpstap            ; e = yes
  3648.     cmp    ax,25            ; UDK status?
  3649.     jne    atdsr3            ; ne = no
  3650.     jmp    rpudk            ; do udk status rpt
  3651. atdsr3:    cmp    ax,26            ; keyboard type?
  3652.     jne    atdsr4            ; ne = no
  3653.     jmp    rpkbd            ; do keyboard type report
  3654. atdsr4:    cmp    ax,256            ; WordPerfect Tek screen query?
  3655.     jne    atdsr5            ; ne = no
  3656.     jmp    tekrpt            ; do Tek report
  3657. atdsr5:    ret                ; must have been an echo
  3658.  
  3659. rpstat:    mov    ttyact,0        ; group output for networks
  3660.     mov    al,CSI            ; operating status query
  3661.     call    prtbout
  3662.     mov    al,'0'            ; tell them we think we are OK
  3663.     call    prtbout
  3664.     mov    ttyact,1        ; end group output for networks
  3665.     mov    al,'n'
  3666.     call    prtbout
  3667.     ret
  3668.  
  3669. rpcup:    mov    ttyact,0        ; group output for networks
  3670.     mov    al,CSI            ; cursor position report
  3671.     call    prtbout
  3672.     mov    al,byte ptr cursor+1    ; get row
  3673.     inc    al            ; map to origin at 1,1 system
  3674.     test    vtemu.vtflgop,decom    ; Origin mode set?
  3675.     jz    rpcup1            ; z = no
  3676.     sub    al,mar_top        ; subtract off top margin
  3677. rpcup1: call    prtnout            ; output the number
  3678.     mov    al,';'
  3679.     call    prtbout
  3680.     mov    al,byte ptr cursor    ; column number
  3681.     inc    al            ; map to origin at 1,1 system
  3682.     call    prtnout
  3683.     mov    ttyact,1        ; end group output for networks
  3684.     mov    al,'R'            ; final char
  3685.     call    prtbout
  3686.     ret
  3687.  
  3688. rpstap:    mov    ttyact,0        ; group output for networks
  3689.     mov    al,CSI            ; printer port query
  3690.     call    prtbout            ; send CSI or ESC [ ? 10 or 13 n 
  3691.     mov    al,'?'            ;  10 = printer ready, 13 = not ready
  3692.     call    prtbout
  3693.     mov    al,'1'
  3694.     call    prtbout
  3695.     mov    ah,ioctl        ; get printer status, via DOS
  3696.     mov    al,7            ; status for output
  3697.     push    bx
  3698.     mov    bx,4            ; std handle for system printer
  3699.     int    dos
  3700.     pop    bx
  3701.     jc    rpstap1            ; c = call failed
  3702.     cmp    al,0ffh            ; code for Ready
  3703.     jne    rpstap1            ; ne = not ready
  3704.     mov    al,'0'            ; ready, send final digit
  3705.     jmp    short rpstap2
  3706. rpstap1:mov    al,'3'            ; not ready, say printer disconnected
  3707. rpstap2:call    prtbout
  3708.     mov    ttyact,1        ; end group output for networks
  3709.     mov    al,'n'            ; final char of response
  3710.     call    prtbout
  3711.     ret
  3712.  
  3713. rpudk:    mov    ttyact,0        ; group output for networks
  3714.     mov    al,CSI            ; response to UDK locked query
  3715.     call    prtbout
  3716.     mov    al,'?'
  3717.     call    prtbout
  3718.     mov    al,20            ; say keys are unlocked (locked=21)
  3719.     call    prtnout
  3720.     mov    ttyact,1        ; end group output for networks
  3721.     mov    al,'n'            ; final char
  3722.     call    prtbout
  3723.     ret
  3724.  
  3725. rpkbd:    mov    ttyact,0        ; group output for networks
  3726.     mov    al,CSI            ; response to kbd type query
  3727.     call    prtbout
  3728.     mov    al,'?'
  3729.     call    prtbout
  3730.     mov    al,27            ; keyboard dialect follows
  3731.     call    prtnout
  3732.     mov    al,';'
  3733.     call    prtbout
  3734.     mov    bl,vtemu.vtchset    ; get Kermit NRC code (0-13)
  3735.     xor    bh,bh
  3736.     mov    al,nrckbd[bx]        ; get DEC keyboard code from table
  3737.     call    prtnout
  3738.     mov    ttyact,1        ; end group output for networks
  3739.     mov    al,'n'
  3740.     call    prtbout
  3741.     ret
  3742.  
  3743. tekrpt:    call    tekinq            ; get Tek screen size and num colors
  3744.     push    cx            ; screen colors
  3745.     push    bx            ; screen width
  3746.     push    ax            ; screen height
  3747.     mov    ttyact,0        ; group output for networks
  3748.     mov    al,CSI            ; response to Tek query
  3749.     call    prtbout
  3750.     mov    al,'?'
  3751.     call    prtbout
  3752.     mov    di,offset emubuf    ; working buffer
  3753.     mov    byte ptr [di],0        ; insert terminator
  3754.     mov    ax,256            ; first parameter
  3755.     call    dec2di            ; write ascii digits
  3756.     mov    byte ptr [di],';'    ; separator
  3757.     inc    di
  3758.     pop    ax            ; get screen height
  3759.     call    dec2di
  3760.     mov    byte ptr [di],';'    ; separator
  3761.     inc    di
  3762.     pop    ax            ; get screen width
  3763.     call    dec2di
  3764.     mov    byte ptr [di],';'    ; separator
  3765.     inc    di
  3766.     pop    ax            ; get number screen color (0, 1 or 16)
  3767.     call    dec2di
  3768.     mov    byte ptr[di],'n'    ; end of sequence
  3769.     inc    di
  3770.     mov    cx,di            ; compute string length
  3771.     mov    di,offset emubuf
  3772.     sub    cx,di
  3773. tekrpt1:mov    al,[di]            ; get a string char
  3774.     inc    di
  3775.     cmp    cx,1            ; last char?
  3776.     ja    tekrpt2            ; a = no
  3777.     mov    ttyact,1        ; end group output for networks
  3778. tekrpt2:call    prtbout            ; send it
  3779.     loop    tekrpt1
  3780.     ret
  3781.  
  3782. atrqtsr:cmp    flags.vtflg,ttheath    ; Heath-19? ESC [ u
  3783.     jne    atrqts1            ; ne = no
  3784.     cmp    nparam,0        ; ought to have no parameters
  3785.     jne    atrqts2            ; ne = oops, not H-19 command, ignore
  3786.     jmp    atrc            ; H19, restore cursor pos and attrib
  3787.     
  3788. atrqts1:cmp    inter,'$'        ; VT320 Terminal State Rpt DECRQTSR?
  3789.     jne    atrqts2            ; ne = no
  3790.     cmp    param,1            ; report required?
  3791.     je    atrqts4            ; e = yes
  3792.     cmp    param,2            ; VT340 color palette report?
  3793.     jne    atrqts1a        ; ne = no
  3794.     call    tekinq            ; get Tek screen state
  3795.     call    tekpal            ; do palette report in Tek emulator
  3796. atrqts1a:ret
  3797. atrqts2:cmp    inter,'&'        ; DECRQUPSS, User preferred Supp Set?
  3798.     je    atrqts5            ; e = yes
  3799.     ret                ; else ignore
  3800. atrqts4:mov    al,DCS            ; Terminal state report
  3801.     call    prtbout            ; output as 7- or 8-bit quantity
  3802.     mov    al,byte ptr param
  3803.     call    prtnout            ; output as ascii digits, no echo
  3804.     mov    al,'$'
  3805.     call    prtbout            ; output char, no echo
  3806.     mov    al,'s'            ; Final char to main DCS part
  3807.     call    prtbout
  3808.     mov    al,STCHR        ; terminator to empty string
  3809.     call    prtbout
  3810.     ret
  3811.  
  3812. atrqts5:mov    al,DCS            ; User Preferred Supplemental Set
  3813.     call    prtbout            ;  report
  3814.     mov    al,'0'            ; assume 94 byte set
  3815.     cmp    upss,94            ; 94 byte set?
  3816.     je    atrqts6            ; e = yes
  3817.     inc    al            ; change to 96 byte size
  3818. atrqts6:call    prtbout
  3819.     mov    al,'!'
  3820.     call    prtbout
  3821.     mov    al,'u'
  3822.     call    prtbout
  3823.     mov    al,upss+1        ; first ident char
  3824.     call    prtbout
  3825.     mov    al,upss+2        ; second char, if any
  3826.     or    al,al
  3827.     jz    atrqts7            ; z = no second char
  3828.     call    prtbout
  3829. atrqts7:mov    al,STCHR
  3830.     call    prtbout
  3831.     ret
  3832.                     ; Request Presentation State Report
  3833. atrqpsr:cmp    inter,'$'        ; proper form?
  3834.     jne    atrqps1            ; ne = no, ignore
  3835.     cmp    param,1            ; cursor report?
  3836.     je    atrqps2            ; e = yes
  3837.     cmp    param,2            ; tabstop report?
  3838.     jne    atrqps1            ; ne = no, ignore
  3839.     jmp    atrqps40        ; do tabstop report
  3840. atrqps1:ret                ; else ignore
  3841.  
  3842. atrqps2:mov    al,DCS            ; cursor report, start
  3843.     call    prtbout
  3844.     mov    al,'1'
  3845.     call    prtbout
  3846.     mov    al,'$'
  3847.     call    prtbout
  3848.     mov    al,'u'
  3849.     call    prtbout
  3850.     mov    al,dh            ; row of cursor
  3851.     inc    al            ; count from 1,1
  3852.     call    prtnout            ; output number
  3853.     mov    al,';'
  3854.     call    prtbout
  3855.     mov    al,dl            ; column of cursor
  3856.     inc    al            ; count from 1,1
  3857.     call    prtnout            ; output number
  3858.     mov    al,';'
  3859.     call    prtbout
  3860.     mov    al,'1'            ; video page, always 1 for VT320
  3861.     call    prtbout
  3862.     mov    al,';'
  3863.     call    prtbout
  3864.     mov    al,40h            ; start bit field template
  3865.     cmp    video_state,1        ; reverse video char writing on?
  3866.     jne    atrqps3            ; ne = no
  3867.     or    al,8            ; set the bit
  3868. atrqps3:call    getblink        ; ah will be non-zero if blinking
  3869.     or    ah,ah            ; blinking?
  3870.     je    atrqps4            ; z = no
  3871.     or    al,4            ; set the bit
  3872. atrqps4:call    getunder        ; ah will be non-zero if underlining
  3873.     or    ah,ah            ; underlining?
  3874.     je    atrqps5            ; z = no
  3875.     or    al,2            ; set the bit
  3876. atrqps5:call    getbold            ; ah will be non-zero if bolding
  3877.     or    ah,ah            ; bold?
  3878.     je    atrqps6            ; z = no
  3879.     or    al,1            ; set the bit
  3880. atrqps6:call    prtbout
  3881.     mov    al,';'
  3882.     call    prtbout
  3883.     mov    al,40h            ; Satt (Selective params), none here
  3884.     call    prtbout            ; output required skeleton
  3885.     mov    al,';'
  3886.     call    prtbout
  3887.     mov    al,40h            ; Sflag (shift/wrap/origin mode)
  3888.     cmp    atwrap,0        ; wrap pending?
  3889.     je    atrqps7            ; e = no
  3890.     or    al,8            ; set the bit
  3891. atrqps7:cmp    SSptr,offset G3set    ; SS3: G3 mapped to GL for next char?
  3892.     jne    atrqps8            ; ne = no
  3893.     or    al,4            ; set the bit
  3894. atrqps8:cmp    SSptr,offset G2set    ; SS2: G2 mapped to GL for next char?
  3895.     jne    atrqps9            ; ne = no
  3896.     or    al,2            ; set the bit
  3897. atrqps9:test    vtemu.vtflgop,decom    ; Origin mode set?
  3898.     jz    atrqps10        ; z = no
  3899.     or    al,1            ; set the bit
  3900. atrqps10:call    prtbout
  3901.     mov    al,';'
  3902.     call    prtbout
  3903.     mov    al,'0'            ; Pgl, say which set is in GL
  3904.     mov    si,GLptr        ; setup for worker
  3905.     call    atrqps30        ; worker returns proper al
  3906.     call    prtbout
  3907.     mov    al,';'
  3908.     call    prtbout
  3909.     mov    al,'0'            ; Pgr, say which set is in GR
  3910.     mov    si,GRptr        ; setup for worker
  3911.     call    atrqps30        ; worker returns proper al
  3912.     call    prtbout
  3913.     mov    al,';'
  3914.     call    prtbout
  3915.     mov    al,40h            ; Scss, char set size bit field
  3916.     call    atrqp15            ; call worker to fill in al
  3917.     call    prtbout    
  3918.     mov    al,';'
  3919.     call    prtbout
  3920.     mov    bx,offset G0set        ; Sdesig, get 1-2 letter ident
  3921.     call    atrqps20        ; G0, let worker fill in response
  3922.     mov    bx,offset G1set
  3923.     call    atrqps20        ; G1, let worker fill in response
  3924.     mov    bx,offset G2set
  3925.     call    atrqps20        ; G2, let worker fill in response
  3926.     mov    bx,offset G3set
  3927.     call    atrqps20        ; G3, let worker fill in response
  3928.     mov    al,STCHR        ; String terminator
  3929.     call    prtbout
  3930.     ret
  3931.  
  3932. ; worker for Character set size reporting
  3933. atrqp15:cmp    G0set+96,gsize        ; is G0 a 96 byte set?
  3934.     jne    atrqp16            ; ne = no
  3935.     or    al,1            ; say 96
  3936. atrqp16:cmp    G1set+96,gsize        ; is G1 a 96 byte set?
  3937.     jne    atrqp17            ; ne = no
  3938.     or    al,2            ; say 96
  3939. atrqp17:cmp    G2set+96,gsize        ; G2 set?
  3940.     jne    atrqp18
  3941.     or    al,4            ; say 96
  3942. atrqp18:cmp    G3set+96,gsize        ; G3 set?
  3943.     jne    atrqp19
  3944.     or    al,8            ; say 96
  3945. atrqp19:ret                ; return with al setup
  3946.  
  3947. ; worker for Character set ident reporting at atrqps16: et seq
  3948. atrqps20:mov    al,[bx+gsize+1]        ; Gn set pointer, first letter
  3949.     call    prtbout
  3950.     mov    al,[bx+gsize+2]        ; second letter
  3951.     or    al,al            ; is there one?
  3952.     jz    atrqps21        ; z = no, nothing there
  3953.     call    prtbout
  3954. atrqps21:ret
  3955.  
  3956. ; worker. Enter with SI holding GLptr or GRptr and al = '0'
  3957. ; Returns al = '0' .. '3' to match set pointed at
  3958. atrqps30:cmp    si,offset G0set        ; si points at G0?
  3959.     je    atrqps31        ; e = yes
  3960.     inc    al            ; try next set
  3961.     cmp    si,offset G1set        ; si points at G1?
  3962.     je    atrqps31
  3963.     inc    al
  3964.     cmp    si,offset G2set        ; si points at G2?
  3965.     je    atrqps31
  3966.     inc    al            ; must be G3
  3967. atrqps31:ret
  3968.  
  3969. atrqps40:mov    al,DCS            ; start tabstop report
  3970.     call    prtbout
  3971.     mov    al,'2'            ; tabs
  3972.     call    prtbout
  3973.     mov    al,'$'
  3974.     call    prtbout
  3975.     mov    al,'u'
  3976.     call    prtbout
  3977.     mov    cl,byte ptr low_rgt    ; right most column number
  3978.     inc    cl            ; number of columns
  3979.     xor    ch,ch
  3980.     push    dx            ; save dx
  3981.     xor    dx,dx            ; dh for done one output, dl = column
  3982.     mov    si,offset tabs        ; active tabs buffer
  3983. atrqps41:call    istabs            ; tab inquiry routine, column is in dl
  3984.     jnc    atrqps43        ; nc = no tab
  3985.     or    dh,dh            ; sent one value already?
  3986.     je    atrqps42        ; e = no, so no separator
  3987.     mov    al,';'            ; separator (DEC used '/')
  3988.     call    prtbout
  3989. atrqps42:mov    al,dl            ; get column
  3990.     inc    al            ; count columns from 1 for host
  3991.     call    prtnout            ; output the number
  3992.     inc    dh            ; say sent a number
  3993. atrqps43:inc    dl            ; next column, say sent one output
  3994.     loop    atrqps41        ; do the rest
  3995.     pop    dx            ; recover dx
  3996.     mov    al,STCHR        ; string terminator
  3997.     call    prtbout
  3998.     ret
  3999.     
  4000. ; Process Restore Presentation Reports, for cursor and tab stops
  4001. ; Uses bytes dinter+5 and dinter+6 as internal variables
  4002. atrp:    cmp    dinter,0+'$'        ; correct intermediate?
  4003.     je    atrp1            ; e = yes
  4004.     jmp    atcrqxx            ; send back "illegal restore" response
  4005. atrp1:    cmp    dparam,1        ; cursor info?
  4006.     je    atrp4            ; e = yes
  4007.     mov    modeset,1        ; say setting tabs
  4008.     call    atrpw            ; call worker to do ascii to binary
  4009.     dec    dl            ; count internally from col 0
  4010.     call    tabset            ; set tab in column dl
  4011. atrp3:    mov    emubufc,0        ; clear the string count
  4012.     ret
  4013.                       ; start cursor info report playback
  4014. atrp4:    cmp    dinter+5,0        ; our internal counter in vacant byte
  4015.     jne    atrp5            ; not initial byte
  4016.     inc    dinter+5        ; point to next item next time
  4017.     call    atrpw            ; ascii to binary worker
  4018.     xchg    dh,dl            ; get row to correct byte
  4019.     mov    dl,byte ptr cursor+1    ; get column
  4020.     jmp    atscu5            ; set the cursor
  4021. atrp5:    cmp    dinter+5,1        ; column?
  4022.     jne    atrp6
  4023.     inc    dinter+5        ; point to next item next time
  4024.     call    atrpw            ; ascii to binary worker
  4025.     mov    dh,byte ptr cursor    ; get row
  4026.     jmp    atscu5            ; set the cursor
  4027. atrp6:    cmp    dinter+5,2        ; page?
  4028.     jne    atrp7
  4029.     inc    dinter+5        ; omit page byte
  4030.     ret
  4031. atrp7:    cmp    dinter+5,3
  4032.     jne    atrp8
  4033.     inc    dinter+5        ; Srend
  4034.     mov    al,emubuf        ; string byte
  4035.     mov    ah,curattr        ; attributes field
  4036.                     ; ought to clear attributes first
  4037.     test    al,1            ; set bold?
  4038.     jz    atrp7a            ; z = no
  4039.     call    setbold
  4040. atrp7a:    test    al,2            ; set underline?
  4041.     jz    atrp7b            ; z = no
  4042.     call    setunder
  4043. atrp7b:    test    al,4            ; set blink?
  4044.     jz    atrp7c            ; z = no
  4045.     call    setblink
  4046. atrp7c:    mov    curattr,ah        ; attributes so far
  4047.     test    al,8            ; set per char rev video?
  4048.     jz    atrp7d            ; z = no
  4049.     cmp    video_state,0        ; reversed already?
  4050.     jne    atrp7d            ; ne = yes
  4051.     call    revideo
  4052.     inc    video_state        ; say reversed now
  4053.     mov    curattr,ah
  4054. atrp7d:    ret
  4055. atrp8:    cmp    dinter+5,4
  4056.     jne    atrp9
  4057.     inc    dinter+5        ; Satt, skip it
  4058.     ret
  4059. atrp9:    cmp    dinter+5,5
  4060.     jne    atrp10
  4061.     inc    dinter+5
  4062.     mov    al,emubuf        ; string byte
  4063.     mov    ah,al
  4064.     and    ah,8            ; autowrap bit
  4065.     mov    atwrap,ah        ; set it
  4066.     mov    SSptr,0            ; say no single shift needed
  4067.     test    al,4            ; SS3 bit?
  4068.     jz    atrp9a            ; z = no
  4069.     mov    SSptr,offset G3set    ; set the pointer
  4070. atrp9a:    test    al,2            ; SS2 bit?
  4071.     jz    atrp9b            ; z = no
  4072.     mov    SSptr,offset G2set    ; set the pointer
  4073. atrp9b:    and    vtemu.vtflgop,not decom ; clear origin bit
  4074.     test    al,1            ; origin mode?
  4075.     jz    atrp9c            ; z = no
  4076.     or    vtemu.vtflgop,decom    ; set origin mode
  4077. atrp9c:    ret
  4078. atrp10:    cmp    dinter+5,6        ; Pgl
  4079.     jne    atrp11
  4080.     inc    dinter+5
  4081.     mov    al,emubuf        ; string byte
  4082.     call    atrpw5            ; call worker to setup bx with ptr
  4083.     mov    GLptr,bx
  4084.     ret
  4085. atrp11:    cmp    dinter+5,7        ; Pgr
  4086.     jne    atrp12
  4087.     inc    dinter+5
  4088.     mov    al,emubuf        ; string byte
  4089.     call    atrpw5            ; call worker to setup bx with ptr
  4090.     mov    GRptr,bx
  4091.     ret
  4092. atrp12:    cmp    dinter+5,8        ; Scss
  4093.     jne    atrp13            ; ne = no
  4094.     inc    dinter+5
  4095.     mov    al,emubuf        ; string byte
  4096.     and    al,0fh            ; strip ascii bias
  4097.     mov    dinter+6,al        ; save here for Sdesig byte, next
  4098.     ret
  4099. atrp13:    cmp    dinter+5,9        ; Sdesig
  4100.     jne    atrp14
  4101.     inc    dinter+5
  4102.     mov    si,offset emubuf    ; string
  4103.     xor    cx,cx            ; init loop counter to 0
  4104. atrp13a:mov    al,'('            ; assume G0 is 94 byte set
  4105.     add    al,cl            ; plus loop index to get set pointer
  4106.     shr    dinter+6,1        ; get set size bit
  4107.     jnc    atrp13b            ; e = correct
  4108.     add    al,4            ; map to 96 byte indicator
  4109. atrp13b:mov    inter,al        ; store size byte as intermediate
  4110.     mov    ninter,1        ; one char
  4111.     cld
  4112. atrp13c:lodsb                ; next string byte
  4113.     test    al,not 2fh        ; is there a second intermediate byte?
  4114.     jnz    atrp13d            ; nz = no
  4115.     mov    inter+1,al        ; store intermediate
  4116.     inc    ninter            ; count them
  4117.     jmp    short atrp13c        ; try again for a Final char
  4118. atrp13d:push    si
  4119.     push    cx
  4120.     mov    bx,offset ansesc    ; table to use
  4121.     call    atdispat        ; dispatch on final char to set ptr
  4122.     pop    cx
  4123.     pop    si
  4124.     inc    cx
  4125.     cmp    cx,3            ; doing last one?
  4126.     jbe    atrp13a            ; be = no, do all four
  4127.     ret
  4128. atrp14:    jmp    atcrqxx            ; send back "illegal restore" response
  4129.  
  4130.                     ; worker, ascii string to decimal byte
  4131. atrpw:    mov    cx,emubufc        ; length of this string
  4132.     jcxz    atrpw3            ; nothing there
  4133.     mov    si,offset emubuf    ; address of string
  4134.     xor    dl,dl            ; init final value
  4135.     cld
  4136. atrpw2:    lodsb                ; read a digit
  4137.     sub    al,'0'            ; ascii to numeric
  4138.     jc    atrpw3            ; c = trouble
  4139.     shl    dl,1            ; previous contents times 10
  4140.     mov    dh,dl
  4141.     shl    dl,1
  4142.     shl    dl,1
  4143.     add    dl,dh
  4144.     add    dl,al            ; plus new value
  4145.     loop    atrpw2            ; do all digits
  4146. atrpw3:    ret
  4147.                        ; char set selector worker
  4148. atrpw5:    cmp    al,'0'            ; bx gets G0set...G3set, based on AL
  4149.     jne    atrpw5a
  4150.     mov    bx,offset G0set
  4151.     ret
  4152. atrpw5a:cmp    al,'1'
  4153.     jne    atrpw5b
  4154.     mov    bx,offset G1set
  4155.     ret
  4156. atrpw5b:cmp    al,'2'
  4157.     jne    atrpw5c
  4158.     mov    bx,offset G2set
  4159.     ret
  4160. atrpw5c:mov    bx,offset G3set
  4161.     ret
  4162.  
  4163.  
  4164. ; VT52 compatibility mode routines.
  4165.  
  4166. ; Return to ANSI mode.
  4167.  
  4168. v52ans: or    vtemu.vtflgop,decanm    ; turn on ANSI flag
  4169.     mov    al,oldterm        ; terminal type at startup
  4170.     cmp    al,ttvt52        ; was VT52 the prev kind?
  4171.     jne    v52ans1            ; ne = no
  4172.     mov    al,ttvt320        ; use VT320
  4173. v52ans1:mov    oldterm,al
  4174.     mov    flags.vtflg,al        ; restore it
  4175.     call    chrdef            ; set default char sets
  4176.     call    atsc            ; save cursor status
  4177.     jmp    ansdsl            ; put "LEDs" back
  4178.  
  4179. ; VT52 cursor positioning.
  4180.  
  4181. v52pos: mov    ttstate,offset v52pc1    ; next state
  4182.     ret
  4183. v52pc1: sub    al,' '-1        ; minus offset
  4184.     xor    ah,ah
  4185.     mov    param,ax        ; stash it here
  4186.     mov    ttstate,offset v52pc2    ; next state
  4187.     ret
  4188. v52pc2: sub    al,' '-1        ; minus offset
  4189.     xor    ah,ah
  4190.     mov    param+2,ax        ; stash here
  4191.     mov    ttstate,offset atnrm    ; reset state to "normal"
  4192.     jmp    atcup            ; position and return
  4193.  
  4194. ; VT52 print controls
  4195.  
  4196. v52ps:    mov    param,0            ; print screen
  4197.     mov    lparam,0
  4198.     jmp    ansprt            ; simulate ESC [ 0 i
  4199. v52pl:    mov    param,1            ; print line
  4200.     jmp    short v52pcom        ; simulate ESC [ ? 1 i
  4201. v52pcb:    mov    param,5            ; Enter printer controller on
  4202.     jmp    short v52pcom        ; simulate ESC [ ? 5 i
  4203. v52pce:    mov    param,4            ; Exit printer controller on
  4204. ;    jmp    short v52pcom        ; simulate ESC [ ? 4 i
  4205. v52pcom:mov    lparam,'?'        ; simulate ESC [ ? <number> i
  4206.     jmp    ansprt            ; process command
  4207.  
  4208. v52sgm:    mov    setptr,offset G0set    ; enter/exit special graphics mode
  4209.     jmp    atdg52            ; construct G0set, AL has 'F' or 'G'
  4210.  
  4211. ; Heath-19 special functions
  4212.  
  4213. h19sans:or    vtemu.vtflgop,decanm    ; Turn on ANSI flag. ESC <
  4214.     jmp    chrdef            ; set default char sets
  4215.                     ; clear screen and go home
  4216.  
  4217. h19ed:    cmp    param,0            ; Erase cursor to end of screen?
  4218.     jne    h19ed2            ; ne = no
  4219.     mov    ax,dx            ; start at cursor
  4220.     mov    bh,byte ptr low_rgt+1    ; lower right corner
  4221.     cmp    bh,dh            ; on status line?
  4222.     jae    h19ed1            ; ae = no
  4223.     mov    bh,dh            ; put end on status line
  4224. h19ed1:    mov    bl,crt_cols        ; physical width
  4225.     dec    bl            ; we count from 0
  4226.     jmp    vtsclr            ; clear it
  4227. h19ed2:    cmp    param,1            ; erase start of display to cursor?
  4228.     je    h19esos            ; e = yes
  4229.     cmp    param,2            ; erase entire screen?
  4230.     je    h19clrs            ; e = yes
  4231.     ret                ; else ignore
  4232.  
  4233.                     ; erase entire screen
  4234. h19clrs:cmp    dh,byte ptr low_rgt+1    ; on status line?
  4235.     ja    h19erl            ; a = yes, do just erase in line
  4236.     xor    dx,dx            ; go to upper left corner
  4237.     call    atscu5            ; do it
  4238.     xor    ax,ax            ; clear screen from (0,0)
  4239.     mov    bh,byte ptr low_rgt+1    ; to lower right corner
  4240.     mov    bl,crt_cols        ; physical width
  4241.     dec    bl            ; we count from 0
  4242.     jmp    vtsclr            ; clear it
  4243.  
  4244. h19erl:    xor    al,al            ; erase whole line
  4245.     mov    bl,crt_cols        ; physical width
  4246.     dec    bl            ; we count from 0
  4247.     jmp    erinline        ; erase whole line, cursor stays put
  4248.  
  4249. h19ero:    xor    al,al            ; erase start of line to cursor
  4250.     mov    bl,dl
  4251.     jmp    erinline        ; clear that part of line
  4252.  
  4253.                     ; erase start of screen to cursor
  4254. h19esos:cmp    dh,byte ptr low_rgt+1    ; on status line?
  4255.     ja    h19ero            ; a = yes, do just erase in line
  4256.     jmp    ersos            ; do regular erase start of screen
  4257.  
  4258. h19wrap:or    vtemu.vtflgop,decawm    ; turn on line wrapping
  4259.     ret
  4260. h19nowrp:and    vtemu.vtflgop,not decawm ; turn off line wrapping
  4261.     ret
  4262.  
  4263. h19herv:mov    ah,curattr        ; get current cursor attribute
  4264.     call    setrev            ; ESC p set reversed video
  4265.     mov    curattr,ah        ; store new attribute byte
  4266.     ret
  4267.  
  4268. h19hxrv:mov    ah,curattr        ; get current cursor attribute
  4269.     call    clrrev            ; ESC q set normal video
  4270.     mov    curattr,ah        ; store new attribute byte
  4271.     ret
  4272.  
  4273. h19sc:    mov    dx,cursor
  4274.     mov    h19cur,dx        ; save cursor position
  4275.     ret
  4276.  
  4277. h19rc:    mov    dx,h19cur        ; saved cursor position
  4278.     jmp    atscu5            ; set cursor and return
  4279.  
  4280.                     ; Heath-19 set mode "ESC x "
  4281. h19smod:mov    ttstate,offset hsmod    ; setup to parse rest of seq
  4282.     ret
  4283. hsmod:    mov    modeset,1        ; say set mode
  4284.     mov    ttstate,offset atnrm
  4285.     sub    al,'0'            ; remove ascii bias
  4286.     jmp    htrsm1            ; perform mode set
  4287.  
  4288. h19cmod:mov    ttstate,offset hcmod    ; setup to parse rest of seq
  4289.     ret
  4290.  
  4291. hcmod:    mov    modeset,0        ; say reset mode
  4292.     mov    ttstate,offset atnrm
  4293.     sub    al,'0'            ; remove ascii bias
  4294.     jmp    htrsm1            ; perform mode reset
  4295.  
  4296. hrcup:    mov    al,escape        ; send "ESC Y row col" cursor report
  4297.     call    prtbout            ; send with no local echo
  4298.     mov    al,'Y'
  4299.     call    prtbout
  4300.     mov    al,byte ptr cursor+1    ; get row
  4301.     add    al,' '            ; add ascii bias
  4302.     call    prtbout            ; send it
  4303.     mov    al,byte ptr cursor    ; get column
  4304.     add    al,' '            ; add ascii bias
  4305.     call    prtbout            ; and send it too
  4306.     ret
  4307.  
  4308. ; Insert/Delete characters and lines
  4309. inslin    proc    near
  4310.     mov    dx,param        ; insert line
  4311.     or    dx,dx            ; any args?
  4312.     jne    insli1            ; ne = yes
  4313.     inc    dx            ; insert one line
  4314. insli1:    mov    scroll,dl        ; lines to scroll
  4315.     mov    dx,cursor        ; current position
  4316.     cmp    dh,mar_bot        ; below bottom margin?
  4317.     ja    insli3            ; a = below bottom margin
  4318.     push    word ptr mar_top
  4319.     mov    mar_top,dh        ; call present position the top
  4320.     call    atscrd            ; scroll down
  4321.     pop    word ptr mar_top    ; restore margins
  4322.     xor    dl,dl            ; go to left margin
  4323.     jmp    atscu5            ; reposition cursor and return
  4324. insli3: ret
  4325. inslin    endp
  4326.  
  4327. dellin    proc    near
  4328.     mov    dx,param        ; delete line(s)
  4329.     or    dx,dx            ; any args?
  4330.     jne    delli1            ; ne = yes
  4331.     inc    dx            ; insert one line
  4332. delli1:    mov    scroll,dl        ; line count
  4333.     mov    dx,cursor        ; where we are presently
  4334.     cmp    dh,mar_bot        ; at or below bottom margin?
  4335.     jae    delli3            ; ae = yes, do not scroll
  4336.     push    word ptr mar_top    ; save current scrolling margins
  4337.     mov    mar_top,dh        ; temp top margin is here
  4338.     call    atscru            ; scroll up
  4339.     pop    word ptr mar_top    ; restore scrolling margins
  4340.     jmp    atscu5            ; restore cursor and return
  4341. delli3: ret
  4342. dellin    endp
  4343.  
  4344. ansich    proc    near            ; ANSI insert characters ESC [ Pn @
  4345.     mov    cx,param
  4346.     or    cx,cx            ; any arguments?
  4347.     jne    ansic1            ; ne = no, ignore
  4348.     inc    cx            ; use one
  4349. ansic1:    push    bx            ; use this as insert/delete flag
  4350.     mov    bh,1            ; do an insert operation
  4351. ansic2:    call    insdel            ; do common insert/delete code
  4352.     pop    bx
  4353.     ret
  4354. ansich    endp
  4355.  
  4356. inschr    proc    near            ; insert open (space) char at cursor
  4357.     push    bx            ; use this as insert/delete flag
  4358.     mov    bh,1            ; do an insert operation
  4359.     mov    cx,1            ; do one character
  4360.     call    insdel            ; do common insert/delete code
  4361.     pop    bx
  4362.     ret
  4363. inschr    endp
  4364.  
  4365. atdelc    proc    near
  4366.     mov    cx,param        ; Delete characters(s)
  4367.     or    cx,cx            ; zero becomes one operation
  4368.     jne    atdelc1
  4369.     inc    cx            ; delete one char. Heath ESC N
  4370. atdelc1:push    bx            ; use this as insert/delete flag
  4371.     mov    bh,-1            ; do a delete operation
  4372. atdelc2:call    insdel            ; do common insert/delete code
  4373.     pop    bx
  4374.     ret
  4375. atdelc    endp
  4376.  
  4377.                     ; Common code for insert/delete char
  4378. insdel    proc    near            ; SI has insert/delete code
  4379.     mov    dx,cursor        ; logical cursor
  4380.     mov    bl,byte ptr low_rgt    ; number of columns on screen - 1
  4381.     push    bx
  4382.     mov    bl,dh            ; cursor row
  4383.     xor    bh,bh            ; bx holds cursor row
  4384.     cmp    linetype [bx],0        ; is line already single width?
  4385.     je    insdel1            ; e = yes
  4386.     add    dl,dl            ; double the cursor column
  4387.     add    cx,cx            ; double repeat count
  4388. insdel1:mov    bl,byte ptr low_rgt    ; physical left margin
  4389.     inc    bl            ; number of screen columns
  4390.     sub    bl,dl            ; width - cursor
  4391.     cmp    cx,bx            ; skipping more than screen width?
  4392.     jbe    insdel2            ; be = no
  4393.     mov    cx,bx            ; limit to screen width please
  4394. insdel2:pop    bx
  4395. ; dh=logical cursor row, dl= logical cursor column, cx has repeat count
  4396. ; bl = logical screen width - 1, bh = +1 for insert, -1 for delete chars.
  4397.     jmp    insdecom        ; do system dependent operation
  4398. insdel    endp
  4399.  
  4400. noins:    mov    insmod,0        ; turn off insert mode
  4401.     ret
  4402.  
  4403. entins:    mov    insmod,0ffh        ; enter insert mode
  4404.     ret
  4405.  
  4406. ; Line type to/from single or double
  4407. linesgl    proc    near            ; convert line to single width char
  4408.     push    ax
  4409.     push    bx
  4410.     push    cx
  4411.     push    dx
  4412.     mov    bx,cursor
  4413.     mov    bl,bh
  4414.     xor    bh,bh            ; bx now holds row
  4415.     cmp    linetype [bx],0        ; is line already single width?
  4416.     je    linsglx            ; e = yes
  4417.     mov    linetype [bx],0        ; say will be single now
  4418.     mov    dh,byte ptr cursor+1    ; row
  4419.     xor    dl,dl            ; start in column 0
  4420.     mov    cl,byte ptr low_rgt    ; number of columns on screen
  4421.     inc    cl
  4422.     shr    cl,1            ; number of columns to do
  4423.     xor    ch,ch
  4424.     push    cx            ; save around loop below
  4425. linsgl1:push    cx            ; save loop counter
  4426.     push    dx
  4427.     shl    dl,1            ; double column number
  4428.     call    direction        ; set dx to desired position
  4429.     call    setpos            ; set cursor position
  4430.     call    getatch            ; read char (al) and attribute (ah)
  4431.     pop    dx
  4432.     push    dx
  4433.     call    direction        ; set dx to desired position
  4434.     call    setpos            ; set cursor position
  4435.     pop    dx
  4436.     call    setatch            ; write char (al) and attribute (ah)
  4437.     inc    dl            ; next column
  4438.     pop    cx
  4439.     loop    linsgl1
  4440.     pop    cx            ; recover column counter
  4441.     mov    dl,cl
  4442. linsgl2:push    cx            ; save counter
  4443.     push    dx
  4444.     call    direction        ; set dx to desired position
  4445.     call    setpos            ; set cursor position
  4446.     mov    ah,scbattr        ; screen background
  4447.     mov    al,' '
  4448.     call    setatch            ; write char
  4449.     pop    dx
  4450.     pop    cx
  4451.     inc    dl            ; next column
  4452.     loop    linsgl2            ; repeat for all characters
  4453. linsglx:pop    dx
  4454.     pop    cx
  4455.     pop    bx
  4456.     pop    ax
  4457.     jmp    atscur            ; update cursor and return
  4458. linesgl    endp
  4459.  
  4460. linedbl    proc    near            ; convert line to double width char
  4461.     push    ax            ; must reset physical cursor
  4462.     push    bx            ; to same char as before expansion
  4463.     push    cx            ; but does not modify variable cursor
  4464.     push    dx
  4465.     mov    bx,cursor
  4466.     mov    bl,bh
  4467.     xor    bh,bh            ; bx now holds row
  4468.     cmp    linetype [bx],0        ; is line single width?
  4469.     jne    lindblx            ; ne = no. nothing to do
  4470.     mov    linetype [bx],1        ; say will be double width now
  4471.     mov    dx,cursor
  4472.     mov    cl,byte ptr low_rgt    ; number of columns on the screen
  4473.     inc    cl
  4474.     xor    ch,ch
  4475.     shr    cl,1            ; number of items to do
  4476.     mov    dl,cl
  4477.     dec    dl
  4478. lindbl1:push    cx            ; save loop counter
  4479.     push    dx
  4480.     call    direction        ; set dx to desired position
  4481.     call    setpos            ; set cursor position
  4482.     call    getatch            ; read char (al) and attribute (ah)
  4483.     pop    dx
  4484.     shl    dl,1            ; double the column number
  4485.     push    dx
  4486.     call    direction        ; set dx to desired position
  4487.     call    setpos            ; set cursor position
  4488.     pop    dx
  4489.     call    setatch            ; write char and attribute
  4490.     inc    dl            ; move to second column of double
  4491.     push    dx
  4492.     call    direction        ; set dx to desired position
  4493.     call    setpos            ; set cursor position
  4494.     pop    dx
  4495.     mov    al,' '            ; space as filler
  4496.     call    setatch            ; write that char
  4497.     dec    dl
  4498.     shr    dl,1
  4499.     dec    dl
  4500.     pop    cx
  4501.     loop    lindbl1
  4502. lindblx:pop    dx
  4503.     pop    cx
  4504.     pop    bx
  4505.     pop    ax
  4506.     jmp    atscur            ; update the cursor and return
  4507. linedbl    endp
  4508.  
  4509. ; Printer support routines
  4510. ansprt    proc near
  4511.     mov    di,offset ansprt0    ; routine to process arguments
  4512.     call    atreps            ; repeat for all parms
  4513.     ret
  4514.  
  4515. ansprt0:mov    ax,param[si]        ; pick up the argument
  4516.     or    ax,ax            ; 0 (print all/part of screen)?
  4517.     jnz    ansprt1            ; nz = no
  4518.     cmp    ninter,0        ; unwanted intermediates?
  4519.     jne    anspr4a            ; ne = got one, illegal here
  4520.     call    pntchk            ; check printer
  4521.     call    pntext            ; do whole screen or scrolling extent
  4522.     jmp    atscu5            ; reposition cursor and return
  4523.  
  4524. ansprt1:cmp    ax,1            ; 1 (print current line)?
  4525.     jne    ansprt4            ; ne = no
  4526.     call    pntchk            ; check for printer ready
  4527.     call    pntlin            ; print current line
  4528.     mov    al,LF
  4529.     call    pntchr
  4530.     call    pntflsh            ; flush printer buffer
  4531.     jmp    atscu5            ; reposition cursor and return
  4532.  
  4533. ansprt4:cmp    ax,4            ; 4 (auto print disable)?
  4534.     jne    ansprt5            ; ne = no
  4535.     cmp    lparam,'?'        ; was it ESC [ ? 4 i
  4536.     jne    anspr4a            ; ne = no, so it was ESC [ 4 i
  4537.     test    anspflg,vtautop        ; check state of print flag
  4538.     jz    anspr4a            ; z = off already
  4539.     or    anspflg,vtautop        ; say auto-print enabled to toggle off
  4540.     jmp    trnprs            ; toggle mode line PRN indicator
  4541. anspr4a:ret
  4542.  
  4543. ansprt5:cmp    ax,5            ; 5 (auto print enable)?
  4544.     jne    ansprtx            ; ne = no
  4545.     call    pntchk            ; check printer, ignore carry ret
  4546.     cmp    lparam,'?'        ; was it ESC [ ? 5 i
  4547.     jne    anspr5a            ; ne = no
  4548.     test    anspflg,vtautop        ; is print already enabled?
  4549.     jnz    ansprtx            ; nz = yes, leave trnprs intact
  4550.     and    anspflg,not vtautop    ; say auto-print disabled to toggle on
  4551.     jmp    trnprs            ; toggle on mode line PRN indicator
  4552.  
  4553. anspr5a:test    anspflg,vtcntp        ; controller print already enabled?
  4554.     jnz    ansprtx            ; nz = yes
  4555.     and    anspflg,not vtautop    ; clear single-char flag for toggling
  4556.     or    anspflg,vtcntp        ; controller print enabled
  4557.     mov    emubufc,0        ; clear string buffer
  4558.     mov    ttstate,offset ansmc    ; do transparent print
  4559.     jmp    trnprs            ; toggle on mode line PRN indicator
  4560. ansprtx:ret
  4561. ansprt    endp
  4562.  
  4563. ; State machine active while Media Copy On (Print Controller ON). Copies all
  4564. ; chars to the printer until and excluding Media Copy Off (ESC [ 4 i) or a
  4565. ; repeated Media Copy On (ESC [ 5 i) has been received or the emulator reset.
  4566. ; New char is in al.
  4567. ansmc    proc    near
  4568.     mov    ttstate,offset ansmc    ; stay in this state
  4569.     cmp    al,escape        ; start a new sequence?
  4570.     je    ansmc1            ; e = yes
  4571.     cmp    al,CSI            ; start a new sequence?
  4572.     je    ansmc0a            ; e = yes
  4573.     mov    emubufc,0        ; say no matched chars
  4574.     jmp    pntchr            ; print char in al, ignore errors
  4575.  
  4576.                     ; CSI seen
  4577. ansmc0a:call    ansmc5            ; playback previous matches
  4578.     mov    ttstate,offset ansmc3    ; get numeric arg
  4579.     mov    emubufc,2        ; say matched "ESC ["
  4580.     mov    word ptr emubuf,escape+256*'['    ; store them
  4581.     ret
  4582.                     ; ESC seen
  4583. ansmc1:    call    ansmc5            ; playback previous matches
  4584.     mov    ttstate,offset ansmc2    ; get left square bracket
  4585.     mov    emubufc,1        ; one char matched
  4586.     mov    emubuf,al        ; store it
  4587.     ret
  4588.  
  4589. ansmc2:    cmp    al,'['            ; left square bracket?
  4590.     je    ansmc2a            ; e = yes
  4591.     call    ansmc5            ; playback previous matches
  4592.     jmp    pntchr            ; print char in al, ignore errors
  4593.  
  4594. ansmc2a:inc    emubufc            ; say matched "ESC ["
  4595.     mov    emubuf+1,al        ; store it
  4596.     call    atpclr            ; clear parser
  4597.     mov    pardone,offset ansmc4    ; where to go when done
  4598.     mov    parfail,offset ansmc5    ; where to go when fail, playback
  4599.     mov    ttstate,offset ansmc3    ; get numeric arg
  4600.     ret
  4601.                     ; CSI or ESC [ seen
  4602. ansmc3:    inc    emubufc            ; another char
  4603.     mov    bx,emubufc        ; qty stored
  4604.     mov    emubuf[bx-1],al        ; store it
  4605.     mov    ah,al            ; check for C0 and C1 controls
  4606.     and    ah,not 80h
  4607.     cmp    ah,20h            ; control range?
  4608.     jb    ansmc5            ; b = yes, mismatch, playback
  4609.     jmp    atparse            ; parse control sequence
  4610.                     ; parse succeeded, al has Final char
  4611. ansmc4:    cmp    al,'i'            ; correct Final char?
  4612.     jne    ansmc5            ; ne = no, playback previous matches
  4613.     cmp    lparam,0        ; missing letter parameter?
  4614.     jne    ansmc5            ; ne = no, mismatch
  4615.     cmp    ninter,0        ; missing intermediates?
  4616.     jne    ansmc5            ; ne = no, mismatch
  4617.     mov    cx,nparam        ; number of parameters
  4618.     xor    bx,bx            ; subscript
  4619. ansmc4a:mov    ax,param[bx]
  4620.     add    bx,2            ; next param
  4621.     cmp    ax,4            ; CSI 4 i  MC OFF?
  4622.     je    ansmc4b            ; e = yes, stop printing
  4623.     loop    ansmc4a            ; keep trying all parameters
  4624.     jmp    short ansmc7        ; forget this one, start over
  4625.  
  4626.                     ; Media OFF found
  4627. ansmc4b:mov    ttstate,offset atnrm    ; return to normal state
  4628.     call    pntflsh            ; flush printer buffer
  4629.     test    anspflg,vtcntp        ; was printing active?
  4630.     jz    ansmc7            ; z = no
  4631.     and    anspflg,not vtcntp    ; yes, disable print controller
  4632.     jmp    trnprs            ; toggle mode line PRN indicator
  4633.  
  4634.                     ; playback emubufc matched chars
  4635. ansmc5:    mov    cx,emubufc        ; matched char count
  4636.     jcxz    ansmc7            ; z = none
  4637.     push    ax            ; save current char in al
  4638.     push    si
  4639.     mov    si,offset emubuf    ; matched sequence, cx chars worth
  4640.     cld
  4641. ansmc6:    lodsb                ; get a char
  4642.     call    pntchr            ; print it, ignore errors
  4643.     loop    ansmc6            ; do all matched chars
  4644.     pop    si
  4645.     pop    ax
  4646.     mov    emubufc,cx        ; clear this counter
  4647. ansmc7:    mov    ttstate,offset ansmc    ; reset state to the beginning
  4648.     ret
  4649. ansmc    endp
  4650.  
  4651. pntlin    proc    near            ; print whole line given by dx
  4652.     push    ax
  4653.     push    bx
  4654.     push    cx
  4655.     push    dx
  4656.     xor    ch,ch
  4657.     mov    cl,byte ptr low_rgt    ; number of columns
  4658.     mov    dl,cl            ; Bios column counter, dh = row
  4659.     inc    cl            ; actual line length, count it down
  4660.     test    vtemu.vtflgop,vswdir    ; writing right to left?
  4661.     jnz    pntlin2            ; nz = yes, do not trim spaces
  4662. pntlin1:call    setpos            ; set cursor
  4663.     call    getatch            ; read char (al) and attribute (ah)
  4664.     cmp    al,' '            ; is this a space?
  4665.     jne    pntlin2            ; no, we have the end of the line
  4666.     dec    dl            ; else move left one column
  4667.     loop    pntlin1            ; and keep looking for non-space
  4668.  
  4669. pntlin2:jcxz    pntlin4            ; z = empty line
  4670.     xor    dl,dl            ; start in column 0, do cl chars
  4671. pntlin3:call    setpos            ; set cursor
  4672.     call    getatch            ; read char (al) and attribute (ah)
  4673.     inc    dl            ; inc to next column
  4674.     call    pntchr            ; print the char (in al)
  4675.     jc    pntlin5            ; c = printer error
  4676.     loop    pntlin3            ; do cx columns
  4677. pntlin4:mov    al,cr            ; add trailing cr for printer
  4678.     call    pntchr
  4679. pntlin5:pop    dx
  4680.     pop    cx
  4681.     pop    bx
  4682.     pop    ax
  4683.     ret                ; C bit controlled by pntchr
  4684. pntlin    endp
  4685.  
  4686. pntext    proc    near            ; print an extent of lines, depending
  4687.     push    ax            ; on flag bit vtextp
  4688.     push    bx
  4689.     push    dx
  4690.     xor    dx,dx            ; assume starting at top left
  4691.     mov    bx,low_rgt        ;  and extending to lower right
  4692.     test    anspflg,vtextp        ; full screen wanted?
  4693.     jnz    pntext1            ; nz = yes, else scrolling region
  4694.     mov    dh,mar_top        ; top of scrolling region
  4695.     mov    bh,mar_bot        ; bottom of scrolling region
  4696. pntext1:call    pntlin            ; print a line
  4697.     jc    pntext2            ; c = printer error
  4698.     mov    al,LF
  4699.     call    pntchr
  4700.     jc    pntext2
  4701.     inc    dh
  4702.     cmp    dh,bh            ; done all requested lines?
  4703.     jbe    pntext1            ; be = not yet, do another
  4704.     test    anspflg,vtffp        ; form feed needed at end?
  4705.     jz    pntext2            ; z = no
  4706.     mov    al,ff
  4707.     call    pntchr            ; print the form feed char
  4708. pntext2:pop    dx
  4709.     pop    bx
  4710.     pop    ax
  4711.     ret
  4712. pntext    endp
  4713.  
  4714. ; Set cursor coordinate DL (row) with consideration for writing direction.
  4715.  
  4716. direction proc    near
  4717.     test    vtemu.vtflgop,vswdir    ; writing left to right?
  4718.     jz    direct1            ; z = yes, no changes needed
  4719.     sub    dl,byte ptr low_rgt    ; right margin column number
  4720.     neg    dl            ; make a positive value again
  4721. direct1:ret
  4722. direction endp
  4723.  
  4724. ; Erase from cursor (DX, inclusive) to end of screen
  4725. ; sense double width/height
  4726. ereos    proc    near
  4727.     mov    ax,dx            ; erase from cursor to end of screen
  4728.     or    dx,dx            ; cursor at home position?
  4729.     jnz    ereos1            ; nz = no
  4730.                     ; e = yes, roll screen before clear
  4731.     push    word ptr mar_top
  4732.     mov    al,byte ptr low_rgt+1    ; bottom row number
  4733.     mov    mar_bot,al
  4734.     mov    mar_top,0        ; row of cursor
  4735.     inc    al            ; number of lines to scroll
  4736.     mov    scroll,al
  4737.     call    atscru            ; scroll them up before erasure
  4738.     pop    word ptr mar_top
  4739.                     ; removes double w/h lines too
  4740.     xor    ax,ax            ; erase from here (home)
  4741.     mov    bh,byte ptr low_rgt+1    ; bh = bottom row number
  4742.     mov    bl,crt_cols        ; bl = physical columns
  4743.     dec    bl            ; physical width (to here)
  4744.     call    vtsclr            ; clear screen
  4745.     ret
  4746. ereos1:    push    dx            ; save dx
  4747.     mov    bl,dh            ; get row number
  4748.     xor    bh,bh
  4749.     cmp    linetype [bx],0        ; single width line?
  4750.     je    ereos2            ; e = yes
  4751.     shl    dl,1            ; physical column is twice logical
  4752. ereos2:    or    dl,dl            ; starting at left margin?
  4753.     je    ereos3            ; e = yes, this goes to single width
  4754.     inc    bl            ; else start on next line
  4755. ereos3:    cmp    bl,byte ptr low_rgt+1    ; at the end of the screen?
  4756.     ja    ereos4            ; a = yes, stop singling-up
  4757.     mov    byte ptr linetype [bx],0 ; set to single width
  4758.     inc    bx
  4759.     jmp    short ereos3        ; loop, reset lines to end of screen
  4760. ereos4:    mov    bx,low_rgt        ; erase from cursor to end of screen
  4761.     mov    bl,crt_cols
  4762.     dec    bl            ; do physical screen width
  4763.     call    vtsclr            ; clear it
  4764.     pop    dx            ; restore dx
  4765.     ret
  4766. ereos    endp
  4767.  
  4768. ; Erase from start of screen to cursor (inclusive), sense double width/height
  4769. ersos    proc    near
  4770.     xor    ax,ax            ; erase from start of screen
  4771.                     ;  to cursor, inclusive
  4772.     xor    bx,bx            ; start at top row (0)
  4773. ersos1:    cmp    bl,dh            ; check rows from the top down
  4774.     jae    ersos2            ; ae = at or below current line
  4775.     mov    byte ptr linetype [bx],0; set line to single width
  4776.     inc    bx            ; inc row
  4777.     jmp    short ersos1        ; look at next line
  4778. ersos2:    or    dl,dl            ; at left margin of current line?
  4779.     jne    ersos3            ; ne = no, leave line width intact
  4780.     mov    byte ptr linetype [bx],0 ; convert to single width    
  4781. ersos3:    mov    bl,dh            ; get row number
  4782.     xor    bh,bh
  4783.     cmp    linetype [bx],0        ; single width line?
  4784.     je    ersos4            ; e = yes
  4785.     shl    dl,1            ; physical column is twice logical
  4786. ersos4:    mov    bx,dx            ; cursor position to bx
  4787.     call    vtsclr            ; clear it
  4788.     ret
  4789. ersos    endp
  4790.  
  4791. ; Erase in line, from column AL to column BL, in row DH
  4792. erinline proc    near
  4793.     mov    ah,dh            ; set row
  4794.     mov    bh,dh
  4795.     push    bx
  4796.     mov    bl,dh            ; get row
  4797.     xor    bh,bh
  4798.     cmp    linetype [bx],0        ; single width line?
  4799.     pop    bx            ; pop does not affect flags
  4800.     je    erinli1            ; e = yes
  4801.     shl    al,1
  4802.     shl    bl,1            ; physical column is twice logical
  4803. erinli1:cmp    bl,crt_cols        ; wider than the physical screen?
  4804.     jb    erinli2            ; b = no, not wider than screen
  4805.     mov    bl,crt_cols
  4806.     dec    bl            ; right most column number
  4807. erinli2:cmp    al,crt_cols
  4808.     jb    erinli3
  4809.     mov    al,crt_cols
  4810.     dec    al
  4811. erinli3:call    vtsclr            ; clear it
  4812.     ret
  4813. erinline endp
  4814.  
  4815. ; Clear screen from AX to BX, where AH = row, AL = column, ditto for BX.
  4816. ; This routine accomodates right to left writing. BX >= AX.
  4817. vtsclr    proc    near
  4818.     test    vtemu.vtflgop,vswdir    ; writing left to right?
  4819.     jz    vtsclr4            ; z = yes
  4820.     cmp    bh,ah            ; same row?
  4821.     je    vtsclr2            ; e = yes
  4822.     push    ax            ; multiple lines
  4823.     push    bx            ; save both coordinates
  4824.     mov    bl,byte ptr low_rgt    ; get right most logical column
  4825.     mov    bh,ah            ; pick just top line
  4826.     call    vtsclr2            ; delete fraction of top line
  4827.     pop    bx            ; recover ending position
  4828.     push    bx
  4829.     inc    ah            ; omit top row, now done
  4830.     dec    bh            ; omit last line, could be fractional
  4831.     cmp    bh,ah            ; any whole lines remaining to delete?
  4832.     jb    vtsclr1            ; b = no, finish up
  4833.     mov    bl,byte ptr low_rgt    ; get right most physical column
  4834.     xor    al,al            ; to end of line (on left)
  4835.     call    atsclr            ; clear top line and whole remainders
  4836. vtsclr1:pop    bx            ; setup for last line to be cleared
  4837.     push    bx            ; get last row again
  4838.     xor    al,al            ; start at logical left margin
  4839.     jmp    short vtsclr3        ; ax and bx are already pushed
  4840.  
  4841. vtsclr2:push    ax            ; erase single line, whole or part
  4842.     push    bx
  4843. vtsclr3:mov    ah,byte ptr low_rgt    ; borrow reg ah (same as bh)
  4844.     sub    ah,bl            ; reflect right to left
  4845.     mov    bl,ah
  4846.     or    bl,bl            ; overflow?
  4847.     jns    vtsclr5            ; ns = no, is ok
  4848.     xor    bl,bl            ; limit to logical screen
  4849. vtsclr5:mov    ah,byte ptr low_rgt
  4850.     sub    ah,al
  4851.     mov    al,ah
  4852.     jns    vtsclr6
  4853.     mov    al,byte ptr low_rgt    ; limit to logical screen
  4854. vtsclr6:mov    ah,bh            ; restore ah
  4855.     xchg    al,bl            ; reverse to get physical ax < bx
  4856.     call    atsclr            ; erase part/all of single line
  4857.     pop    bx
  4858.     pop    ax
  4859.     ret
  4860.                     ; for writing left to right
  4861. vtsclr4:jmp    atsclr            ; do normal erasure and return
  4862. vtsclr    endp
  4863.  
  4864. ; routines supporting scrolling and double width/height chars
  4865. ; scroll has number of lines to scroll
  4866. atscru    proc    near            ; scroll screen up one line
  4867.     push    ax            ; assumes dx holds cursor position
  4868.     push    bx            ; returns with dx = old row, new col
  4869.     push    cx
  4870.     push    si
  4871.     xor    bh,bh
  4872.     mov    bl,mar_top        ; top line to move
  4873.     xor    ch,ch
  4874.     mov    cl,scroll        ; number of lines to move
  4875.     mov    al,mar_bot        ; bottom line to scroll
  4876.     sub    al,bl            ; number of lines minus 1
  4877.     inc    al            ; number of lines
  4878.     cmp    al,cl            ; scrolling region smaller than scroll?
  4879.     jge    atscru1            ; ge = no, is ok
  4880.     mov    scroll,al        ; limit to region
  4881.     cmp    al,1            ; at least one line to scroll?
  4882.     jge    atscru1            ; ge = yes
  4883.     mov    scroll,1        ; no, force one
  4884. atscru1:mov    al,scroll
  4885.     mov    ah,byte ptr low_rgt+1    ; last text line on screen
  4886.     inc    ah            ; number of screen lines
  4887.     cmp    al,ah            ; exceeds number of lines on screen?
  4888.     jbe    atscru8            ; be = scrolling not more than that
  4889.     mov    al,ah            ; limit to screen length
  4890.     mov    scroll,al
  4891. atscru8:xor    ah,ah
  4892.     mov    si,ax            ; scroll interval
  4893.     mov    bl,mar_top
  4894.     mov    cl,mar_bot
  4895.     sub    cl,bl
  4896.     inc    cl            ; number  of lines in region
  4897.     sub    cl,scroll        ; cx = those needing movement
  4898.     cmp    cl,0
  4899.     jle    atscru3
  4900. atscru2:mov    al,linetype[bx+si]    ; get old type
  4901.     mov    linetype[bx],al        ; copy to new higher position
  4902.     inc    bx
  4903.     loop    atscru2
  4904. atscru3:mov    bl,mar_bot        ; set fresh lines to single attribute
  4905.     mov    cl,scroll        ; number of fresh lines (qty scrolled)
  4906.     xor    ch,ch
  4907. atscru4:mov    linetype[bx],0
  4908.     dec    bx
  4909.     loop    atscru4            ; clear old bottom lines
  4910.     mov    bl,dh            ; get row of cursor
  4911.     xor    bh,bh
  4912.     cmp    linetype[bx],0        ; single width?
  4913.     je    atscru5            ; e = yes
  4914.     shr    dl,1            ; reindex to single width columns
  4915. atscru5:pop    si
  4916.     pop    cx
  4917.     pop    bx
  4918.     pop    ax
  4919.     test    anspflg,vtcntp        ; controller print active?
  4920.     jz    atscru6            ; z = no, ok to change screen
  4921.     ret                ;  else keep screen intact
  4922. atscru6:jmp    vtscru            ; call & ret the msy scroll routine
  4923. atscru    endp
  4924.  
  4925. atscrd    proc    near            ; scroll screen down scroll lines
  4926.     push    ax            ; assumes dx holds cursor position
  4927.     push    bx            ; returns with dx = old row, new col
  4928.     push    cx
  4929.     push    si
  4930.     xor    ch,ch
  4931.     mov    cl,scroll        ; number of lines to scroll
  4932.     xor    bh,bh
  4933.     mov    bl,mar_bot        ; bottom line to move
  4934.     mov    al,bl
  4935.     xor    ah,ah
  4936.     sub    al,mar_top        ; number of lines minus 1
  4937.     inc    al            ; number of lines
  4938.     cmp    al,cl            ; scrolling region smaller than scroll?
  4939.     jge    atscrd1            ; ge = no, is ok
  4940.     mov    scroll,al        ; limit to region
  4941.     cmp    al,1            ; at least one line to scroll?
  4942.     jge    atscrd1            ; ge = yes
  4943.     mov    scroll,1        ; no, force one
  4944. atscrd1:mov    al,scroll
  4945.     mov    si,ax            ; si = scroll
  4946.     mov    bl,dh            ; get row of cursor
  4947.     xor    bh,bh            ; make into an index
  4948.     sub    bl,scroll        ; si + this bx will be new bottom line
  4949.     mov    cl,bl
  4950.     sub    cl,mar_top
  4951.     inc    cl
  4952.     cmp    cl,0
  4953.     jle    atscrd3
  4954. atscrd2:mov    al,linetype[bx]        ; get old line's type
  4955.     mov    linetype[bx+si],al    ; copy to new lower position
  4956.     dec    bx
  4957.     loop    atscrd2
  4958. atscrd3:mov    bl,mar_top        ; start with this line
  4959.     xor    bh,bh
  4960.     mov    cl,scroll        ; number of lines scrolled
  4961.     xor    ch,ch
  4962. atscrd4:mov    linetype[bx],0        ; clear new top lines
  4963.     inc    bx
  4964.     loop    atscrd4
  4965.     mov    bl,dh            ; get row of cursor
  4966.     xor    bh,bh
  4967.     cmp    linetype[bx],0        ; single width?
  4968.     je    atscrd5            ; e = yes
  4969.     shr    dl,1            ; reindex to single width columns
  4970. atscrd5:pop    si
  4971.     pop    cx
  4972.     pop    bx
  4973.     pop    ax
  4974.     test    anspflg,vtcntp        ; controller print active?
  4975.     jz    atscrd6            ; z = no, ok to change screen
  4976.     ret                ;  else keep screen intact
  4977. atscrd6:jmp    vtscrd            ; call & ret the msy scroll routine
  4978. atscrd    endp
  4979.  
  4980. ; Returns carry set if column in DL is a tab stop, else carry clear.
  4981. ; Enter with column number in DL (starts at column 0, max of swidth-1)
  4982. ; and tabstop buffer offset in SI.
  4983. istabs    proc    near
  4984.     push    bx
  4985.     push    cx
  4986.     mov    cl,dl            ; column number (0 to swidth-1)
  4987.     and    cl,00000111b        ; keep bit in byte (0-7)
  4988.     inc    cl            ; map to 1-8
  4989.     mov    bl,dl            ; column
  4990.     shr    bl,1            ; bl / 8 to get byte
  4991.     shr    bl,1
  4992.     shr    bl,1
  4993.     xor    bh,bh            ; clear high byte
  4994.     mov    bl,[si+bx]        ; get a byte of tab bits
  4995.     ror    bl,cl            ; rotate to put tab-set bit into carry
  4996.     pop    cx
  4997.     pop    bx
  4998.     ret
  4999. istabs    endp
  5000.  
  5001. ; Modify (set/clear) a tabstop. Enter with DL holding column (0 to swidth-1)
  5002. ; Set a tabstop into buffer pointed at by SI.
  5003. tabset    proc    near
  5004.     mov    modeset,1        ; set a tabstop
  5005.     jmp    short modtabs
  5006. tabset    endp
  5007.  
  5008. ; Clear a tabstop
  5009. tabclr    proc    near
  5010.     mov    modeset,0        ; clear a tabstop
  5011.     jmp    short modtabs
  5012. tabclr    endp
  5013.  
  5014. ; Worker for set/clear tabstop, si has pointer to tabstops array
  5015. modtabs:push    bx
  5016.     push    cx
  5017.     mov    cl,dl            ; column number (0 to swidth-1)
  5018.     and    cl,00000111b        ; keep bit in byte (0-7)
  5019.     mov    ch,1            ; tab bit to change
  5020.     shl    ch,cl            ; shift to bit-in-byte position
  5021.     mov    bl,dl            ; column
  5022.     shr    bl,1            ; bl / 8 to get byte
  5023.     shr    bl,1
  5024.     shr    bl,1
  5025.     xor    bh,bh            ; clear high byte
  5026.     mov    cl,[si+bx]        ; get byte of tabs bits
  5027.     not    ch            ; invert bit marker to create hole
  5028.     and    cl,ch            ; clear the tab bit
  5029.     not    ch            ; recover setting pattern
  5030.     cmp    modeset,0        ; clear the tab bit?
  5031.     jz    modtab1            ; z = yes
  5032.     or    cl,ch            ; set the tab bit
  5033. modtab1:mov    [si+bx],cl        ; store tab byte
  5034.     pop    cx
  5035.     pop    bx
  5036.     ret
  5037.  
  5038. ; This routine initializes the VT  setups at startup. It is called from
  5039. ; procedure lclyini in module msyibm.
  5040. vsinit    proc    near
  5041.     mov    vtemu.vtflgst,vsdefaults ; Init to defaults in mssdef.h
  5042.     mov    vtemu.vtflgop,vsdefaults ; Init runtime state to setup items
  5043.     mov    savflgs,vsdefaults
  5044.     mov    iniflgs,vsdefaults
  5045.     mov    insmod,0        ; turn off insert mode
  5046.     xor    dl,dl            ; Column 1 has no tab stop
  5047.     mov    si,vtemu.vttbs        ; from the cold-start buffer
  5048.     call    tabclr            ; clear that tabstop
  5049.     mov    cl,crt_cols        ; physical screen width (80)
  5050.     dec    cl            ; we count from column 0
  5051.     mov    ch,crt_lins        ; physical screen length-1
  5052.     dec    ch            ; we count from row 0
  5053.     mov    low_rgt,cx        ; store active text area
  5054.     push    es
  5055.     push    ds
  5056.     pop    es
  5057.     cld
  5058.     mov    al,1            ; set tabs at columns 9, spaced by 8
  5059.     mov    cx,(swidth-1)/8        ; bytes to do, at 8 bits/byte
  5060.     mov    di,offset deftabs+1    ; starting byte for column 9 (1...)
  5061.     rep    stosb
  5062.     mov    cx,slen            ; clear linetype array
  5063.     mov    di,offset linetype
  5064.     rep    stosb
  5065.     pop    es
  5066.     mov    vtemu.vttbst,offset tabs ; addrs of active tabs for STATUS
  5067.     mov    vtemu.vttbs,offset deftabs  ; addrs of tabs for setup (SET)
  5068.     call    cpytabs            ; copy default to active
  5069.     mov    vtemu.att_ptr,offset att_normal  ; ptr to video attributes
  5070.     mov    ah,byte ptr low_rgt    ; right most column (counted from 0)
  5071.     sub    ah,8            ; place marker 9 columns from margin
  5072.     mov    belcol,ah        ; store column number to ring bell
  5073.     ret
  5074. vsinit    endp
  5075.  
  5076. ; Initialization routine.
  5077. ; Enter with dl = index for baud rate table
  5078. ; dh = parity in bits 4-7, number of data bits in bits 0-3
  5079. ansini    proc    near
  5080.     mov    ax,vtemu.vtflgst    ; setup flags
  5081.     mov    vtemu.vtflgop,ax
  5082.     mov    iniflgs,ax
  5083.     mov    savflgs,ax
  5084.     mov    al,flags.vtflg        ; get current terminal type
  5085.     mov    oldterm,al        ; remember it here for soft restarts
  5086.     mov    anspflg,0        ; clear printing flag
  5087.     mov    al,byte ptr low_rgt    ; right most column (counted from 0)
  5088.     sub    al,8            ; place marker 9 columns from margin
  5089.     mov    belcol,al        ; store column number to ring bell
  5090.     cmp    dl,lbaudtab        ; out of range index?
  5091.     jb    ansin1            ; b = no, store it
  5092.     mov    dl,lbaudtab-2        ; yes, make it the maximum (128)
  5093. ansin1: mov    baudidx,dl        ; save baud rate index
  5094.     mov    al,dh            ; get parity/number of databits
  5095.     and    al,0FH            ; isolate number of databits
  5096.     mov    datbits,al        ; save
  5097.     mov    cl,4
  5098.     shr    dh,cl            ; isolate parity code
  5099.     cmp    dh,lpartab        ; out of range code?
  5100.     jb    ansin2            ; b = no, store it
  5101.     mov    dh,lpartab-1        ; make it the maximum
  5102. ansin2: mov    parcode,dh        ; save
  5103.     mov    cl,crt_cols        ; physical screen number columns (80)
  5104.     dec    cl            ; we count from column 0 here
  5105.     mov    ch,crt_lins        ; physical screen number rows-1 (24)
  5106.     dec    ch            ; we count from row 0 here
  5107.     mov    oldscrn,cx        ; remember old screen dimensions
  5108.     mov    low_rgt,cx        ; save as active text screen size
  5109.     jmp    atreset            ; reset everything
  5110. ansini    endp
  5111.  
  5112. atxreset proc    near            ; Reset via host command
  5113.     cmp    nparam,0        ; need no Parameters, no Intermediates
  5114.     jne    atxres1            ; ne = not a reset
  5115.     cmp    ninter,0        ; any intermediates?
  5116.     je    atreset            ; e = none, it is a reset
  5117. atxres1:ret                ; ignore command
  5118. atxreset endp
  5119.  
  5120. atreset    proc    near            ; Reset-everything routine
  5121.     mov    cursor,0        ; cursor is at 0,0
  5122.     mov    al,1            ; assume underline cursor
  5123.     test    vtemu.vtflgst,vscursor    ; kind of cursor in setup
  5124.     jnz    atres0            ; nz = underline
  5125.     dec    al            ; else say block
  5126. atres0:    mov    atctype,al        ; VTxxx cursor type
  5127.     mov    h19cur,0        ; Heath-19 saved cursor
  5128.     mov    dspstate,0        ; saved modeline state
  5129.     call    udkclear        ; clear User Definable Key contents
  5130.     push    vtemu.vtflgst        ; setup flags
  5131.     pop    vtemu.vtflgop        ; operational flags
  5132.     and    vtemu.vtflgop,not vscntl ; assume no 8-bit controls
  5133.     mov    al,oldterm        ; get terminal at entry time
  5134.     mov    flags.vtflg,al        ; use it again
  5135.     test    al,ttvt102+ttvt100+tthoney ; VT100 class?
  5136.     jnz    atres1            ; nz = yes, turn on ansi mode
  5137.     test    al,ttvt320+ttvt220    ; VT320/VT220?
  5138.     jz    atres1a            ; z = no, no ansi, no 8-bit controls
  5139.     test    vtemu.vtflgst,vscntl    ; want 8-bit controls?
  5140.     jz    atres1            ; z = no
  5141.     or    vtemu.vtflgop,vscntl    ; turn on 8-bit controls
  5142. atres1:    or    vtemu.vtflgop,decanm    ; turn on ANSI mode
  5143. atres1a:mov    mar_top,0        ; reset scrolling region
  5144.     mov    al,byte ptr low_rgt+1
  5145.     mov    mar_bot,al
  5146.     mov    param[0],0        ; setup call to atleds
  5147.     xor    si,si
  5148.     call    atleds            ; clear the LED indicators
  5149.     call    ansdsl            ; update mode line
  5150.     call    cpytabs            ; initialize tab stops
  5151.     test    flags.vtflg,ttvt320+ttvt220+ttvt102+ttvt100+tthoney
  5152.     jz    atres1c            ; z = no
  5153.     mov    al,vtemu.vtchset    ; setup char set
  5154.     cmp    al,1            ; in range for NRCs?
  5155.     jb    atres1c            ; b = no
  5156.     cmp    al,12            ; highest NRC ident?
  5157.     ja    atres1c            ; a = not NRC
  5158.     or    vtemu.vtflgop,vsnrcm    ; set NRC flag bit to activate NRCs
  5159. atres1c:mov    vtemu.vtchop,al        ; remember char set
  5160.     call    chrdef            ; set default character sets
  5161.     call    vtbell            ; ring bell like VT100
  5162.     cmp    flags.modflg,2        ; mode line owned by host?
  5163.     jne    atres2            ; ne = no
  5164.     mov    flags.modflg,1        ; say now owned by us
  5165.                     ; ATRES2 used in 80/132 col resetting
  5166. ATRES2:    mov    cx,slen            ; typically 24 but do max lines
  5167.     xor    di,di
  5168. atres3:    mov    linetype[di],0        ; clear the linetype array to single
  5169.     inc    di            ; width/height characters
  5170.     loop    atres3
  5171.            mov    ah,att_normal        ; get present normal coloring
  5172.     mov    scbattr,ah        ; set background attributes
  5173.     mov    curattr,ah        ; and cursor attributes
  5174.     test    vtemu.vtflgop,vsscreen    ; want reverse video?
  5175.     jz    atres4            ; z = no
  5176.     call    atrss2            ; reverse screen and attributes (ah)
  5177. atres4:    mov    video_state,0        ; say normal per char video
  5178.     xor    ax,ax            ; starting location
  5179.     mov    bh,crt_lins        ; number or rows on screen
  5180.     dec    bh            ; count from 0
  5181.     mov    bl,crt_cols        ; number of columns on screen
  5182.     dec    bl            ; count from 0
  5183.     call    atsclr            ; clear the whole screen
  5184.     mov    dx,cursor        ; get cursor
  5185.     call    atscu5            ; set cursor
  5186.     call    atsctyp            ; set right cursor type
  5187.     cmp    flags.modflg,1        ; mode line on and owned by us?
  5188.     jne    atres5            ; ne = no, leave it alone
  5189.     test    yflags,modoff        ; mode line supposed to be off?
  5190.     jnz    atres5            ; nz = yes
  5191.     push    dx
  5192.     call    modlin            ; write normal mode line
  5193.     pop    dx
  5194. atres5:    call    atpclr            ; clear parser work area
  5195.     xor    ax,ax
  5196.     mov    parstate,ax        ; reset parser
  5197.     mov    emubufc,ax        ; clear work buffer
  5198.     mov    atwrap,al        ; clear wrap flag
  5199.     mov    SSptr,ax        ; clear single shift flag
  5200.     mov    insmod,al        ; reset insert mode
  5201.     mov    h19stat,al        ; clear heath extended status byte
  5202.     mov    h19ctyp,1        ; Heath-19 cursor to underline
  5203.     mov    anspflg,al        ; clear printer flag
  5204.     call    atsc            ; save cursor information
  5205.     mov    ttstate,offset atnrm    ; normal state
  5206.     ret
  5207. atreset    endp
  5208.  
  5209. ; Re-initialization routine. Called when Term was called but screen was
  5210. ; restored from a previously saved screen, etc.
  5211. ansrei    proc    near
  5212.     call    atsctyp            ; set cursor type [rbv]
  5213.     call    getpos            ; get cursor position from msy
  5214.     mov    cursor,dx        ; dh = row, dl = column
  5215.     mov    cl,crt_cols        ; physical screen number columns (80)
  5216.     dec    cl            ; we count from column 0 here
  5217.     mov    ch,crt_lins        ; physical screen number rows-1 (24)
  5218.     dec    ch            ; we count from row 0 here
  5219.     mov    low_rgt,cx        ; save as active text screen size
  5220.     test    vtemu.vtflgop,deccol    ; want 80 columns?
  5221.     jnz    ansre2            ; nz = no
  5222.     cmp    byte ptr low_rgt,79    ; want 80 cols. Is active screen wider?
  5223.     jbe    ansre2            ; be = no
  5224.     mov    byte ptr low_rgt,79    ; narrow down to 80 columns
  5225. ansre2:    call    direction        ; cursor to writing direction column
  5226.     mov    cursor,dx        ; store as logical position
  5227.     push    cx            ; save current physical screen size
  5228.     call    stblmds            ; check settable modes, set flags
  5229.     pop    cx
  5230.     cmp    cx,oldscrn        ; has screen size changed?
  5231.     je    ansre3            ; e = no, same as last time
  5232.     mov    oldscrn,cx        ; remember new size 
  5233.     mov    mar_top,0        ; reset scrolling region
  5234.     mov    al,byte ptr low_rgt+1
  5235.     mov    mar_bot,al
  5236.     jmp    atres2            ; better do soft reset
  5237. ansre3:    ret
  5238. ansrei    endp
  5239.  
  5240. ; This routine checks to see whether any of the settable modes have changed
  5241. ; (things that can be changed in both SETUP and by host commands), and
  5242. ; changes those that need to be changed.  TMPFLAGS has the new VT100 setup
  5243. ; flags, VTFLAGS has the old. This routine also updates VTFLAGS.
  5244. ; Revised by to allow MSY to reset scbattr when not in connect mode,
  5245. ; to do "soft reset" if terminal type has changed, and to do a screen clear
  5246. ; reset if the actual screen colors have changed.
  5247.  
  5248. stblmds proc    near
  5249.     mov    al,flags.vtflg        ; get current terminal type
  5250.     cmp    al,oldterm        ; same as before?
  5251.     je    stblm10            ; e = yes, skip over soft reset
  5252.     mov    oldterm,al        ; remember current terminal type
  5253.     mov    insmod,0        ; reset insert mode flag
  5254.     and    iniflgs,not vsnrcm    ; turn off NRC bit from last time
  5255.     mov    mar_top,0        ; reset top scrolling margin
  5256.     mov    al,byte ptr low_rgt+1    ; and scrolling margin
  5257.     mov    mar_bot,al        ; to last normal line on screen
  5258.     mov    ah,byte ptr low_rgt    ; right most column (counted from 0)
  5259.     sub    ah,8            ; place marker 9 columns from margin
  5260.     mov    belcol,ah        ; store column number to ring bell
  5261.     push    bx            ; save this register around loop
  5262.     mov    bx,offset linetype    ; setup to clear double width chars
  5263.     mov    cx,slen            ; number of linetype slots to clear
  5264. stblm0:    mov    byte ptr [bx],0        ; clear the linetype array to single
  5265.     inc    bx            ;  width characters
  5266.     loop    stblm0            ; do each line (1 byte per line)
  5267.     pop    bx            ; restore bx
  5268.     test    flags.vtflg,ttvt320+ttvt220+ttvt102+ttvt100+tthoney
  5269.     jz    stblm10            ; z = no
  5270.     or    vtemu.vtflgop,decanm    ; set ansi flag bit
  5271.  
  5272. stblm10:mov    al,vtemu.vtchset    ; setup character set
  5273.     cmp    al,vtemu.vtchop        ; operational character set
  5274.     je    stblm3            ; e = same, no changes needed
  5275.     mov    vtemu.vtchop,al        ; remember this set
  5276.     and    vtemu.vtflgop,not vsnrcm ; clear NRC active bit
  5277.     and    vtemu.vtflgst,not vsnrcm
  5278.     cmp    al,1            ; in range for NRC?
  5279.     jb    stblm11            ; b = no
  5280.     cmp    al,12            ; above NRCs?
  5281.     ja    stblm11            ; a = yes
  5282.     or    vtemu.vtflgop,vsnrcm    ; set NRC active bit
  5283.     or    vtemu.vtflgst,vsnrcm
  5284.     and    vtemu.vtflgop,not vscntl ; no 8-bit controls
  5285. stblm11:call    chrdef            ; init char sets
  5286.  
  5287. stblm3:    mov    ax,iniflgs        ; flags at last entry
  5288.     xor    ax,vtemu.vtflgst    ; find which setup ones have changed
  5289.     test    ax,deccol        ; screen width?
  5290.     jz    stblm3b            ; z = no, don't touch it
  5291.     mov    ax,vtemu.vtflgst    ; Setup bits
  5292.     and    ax,deccol        ; select screen width
  5293.     and    vtemu.vtflgop,not deccol ; clear operational flag bit
  5294.     or    vtemu.vtflgop,ax    ; set current width desired
  5295.     or    al,ah            ; collapse all bits
  5296.     mov    modeset,al        ; non-zero if 132 columns
  5297.     mov    al,3            ; setup call to atrsm6
  5298.     call    atrsm6            ; adjust display width
  5299.  
  5300. stblm3b:cmp    vtclear,1        ; screen need updating?
  5301.     jb    stblm9            ; b = no
  5302.     ja    stblm3a            ; 2 or more means do a reset
  5303.     mov    ah,att_normal        ; 1, get new normal attributes setting
  5304.     mov    scbattr,ah        ; store new values
  5305.     mov    curattr,ah
  5306.     jmp    short stblm9
  5307. stblm3a:mov    cursor,0        ; reset cursor position
  5308.     jmp    atres2            ; go to semi-reset
  5309.  
  5310.                     ; check on screen normal/reversed
  5311. stblm9:    mov    ax,iniflgs        ; flags at last entry
  5312.     xor    ax,vtemu.vtflgst    ; find which setup ones have changed
  5313.     test    ax,vsscreen        ; screen background?
  5314.     jz    stblm8            ; z = no, don't touch it
  5315.     test    vtemu.vtflgop,vsscreen    ; reverse video flag set?
  5316.     jnz    stblm5            ; nz = yes, do it
  5317.     and    vtemu.vtflgop,not vsscreen ; cleared (normal video)
  5318.     jmp    short stblm6        ; reverse everything
  5319. stblm5: or    vtemu.vtflgop,vsscreen    ; set (reverse video)
  5320. stblm6: call    atrss2            ; reverse screen and cursor attribute
  5321.     mov    ah,scbattr        ; reset saved attribute also
  5322.     mov    savecu+svattr_index,ah
  5323. stblm8:    cmp    flags.modflg,2        ; mode line enabled and owned by host?
  5324.     je    stblm9a            ; e = yes, leave it alone
  5325.     call    clrmod            ; clear the mode line
  5326.     test    yflags,modoff        ; mode line supposed to be off?
  5327.     jnz    stblm9a            ; nz = yes
  5328.     call    modlin            ; write normal mode line
  5329.     and    yflags,not modoff    ; say modeline is not toggled off
  5330. stblm9a:mov    dx,cursor        ; logical cursor
  5331.     push    dx
  5332.     call    direction        ; set cursor for writing direction
  5333.     call    setpos            ; set the cursor physical position
  5334.     pop    dx
  5335.     push    vtemu.vtflgst
  5336.     pop    iniflgs            ; remember setup flags at this entry
  5337.     ret
  5338. stblmds endp
  5339.  
  5340. ; Routine called when something is typed on the keyboard
  5341.  
  5342. anskbi    proc    near
  5343.     mov    ttkbi,0FFH        ; just set a flag
  5344.     ret
  5345. anskbi    endp
  5346.  
  5347.  
  5348. ; This routine copies the new tab stops when they have changed.
  5349. ; Copies all 132 columns.
  5350. cpytabs proc    near
  5351.     mov    cx,(swidth+7)/8        ; number of bytes in screen width
  5352.     jcxz    cpytab1            ; z = none to do
  5353.     mov    si,offset deftabs    ; source is setup array
  5354.     mov    di,offset tabs        ; destination is active array
  5355.     push    es            ; save es
  5356.     push    ds
  5357.     pop    es            ; set es to data segment
  5358.     cld
  5359.     rep    movsb            ; do the copy
  5360.     pop    es            ; recover es
  5361. cpytab1:ret
  5362. cpytabs endp
  5363.  
  5364. ; Routine to toggle between text and Tek graphics modes. No arguments.
  5365. ; Text terminal type remembered in byte OLDTERM.
  5366. ans52t    proc    near
  5367.     mov    al,flags.vtflg
  5368.     cmp    al,tttek        ; in Tek mode now?
  5369.     je    ans52b            ; e = yes, exit Tek mode
  5370.     cmp    tekflg,0        ; doing Tek sub mode?
  5371.     jne    ans52b            ; ne = yes
  5372.     test    denyflg,tekxflg        ; is Tek mode disabled?
  5373.     jnz    ans52a            ; nz = yes, disabled
  5374.     mov    oldterm,al        ; save text terminal type here
  5375.     call    atsc            ; save cursor and associated data
  5376.     mov    flags.vtflg,tttek    ; set Tek mode
  5377.     mov    tekflg,0        ; not a sub mode
  5378.     call    tekini            ; init Tek to switch screens
  5379. ans52a:    jmp    atnorm            ; normal state and return
  5380.  
  5381. ans52b:    call    tekend            ; exit Tek graphics mode
  5382.     mov    al,oldterm
  5383.     mov    flags.vtflg,al        ; say text terminal now
  5384.     call    atrc            ; restore cursor etc
  5385.     call    atsc            ; save cursor etc
  5386.     call    ansdsl            ; remove or redisplay "LEDs"
  5387.     jmp    atnorm            ; set state to "normal" and return
  5388. ans52t    endp
  5389.  
  5390. ;  Honeywell VIP 3.1 i.d. string [FD]
  5391. athoney proc    near
  5392.     cmp    flags.vtflg,tthoney    ; Honeywell mode?
  5393.     jne    athone3            ; ne = no, ignore
  5394.     mov    ttyact,0        ; group for networks
  5395.     mov    cx,VIPstrl        ; length of string
  5396.     mov    si,offset VIPstr    ; ptr to string
  5397.     cld
  5398. athone1:lodsb                ; get a byte
  5399.     push    cx            ; save regs
  5400.     push    si
  5401.     call    prtbout            ; print WITHOUT echo
  5402.     pop    si
  5403.     pop    cx
  5404.     cmp    cx,1            ; last char?
  5405.     ja    athone2            ; a = not yet
  5406.     mov    ttyact,1        ; end of network grouping
  5407. athone2:loop    athone1            ; loop for all characters
  5408. athone3:jmp    atnorm
  5409. athoney endp
  5410.  
  5411. athoncls proc    near            ; Honeywell ESC accent  screen clear
  5412.     cmp    nparam,0        ; absence of parameters?
  5413.     jne    athoncl1        ; ne = no, fail
  5414.     cmp    ninter,0        ; any intermediates?
  5415.     jne    athoncl2        ; ne = yes, not this item
  5416.     cmp    flags.vtflg,tthoney    ; doing Honeywell emulation?
  5417.     jne    athoncl1        ; ne = no
  5418.     xor    dx,dx            ; move cursor to Home position
  5419.     call    ereos            ; erase to end of screen
  5420.     xor    dx,dx
  5421.     jmp    atscu5            ; set cursor and return
  5422. athoncl1:ret
  5423. athoncl2:jmp    atdgnrc            ; try Norwegian/Danish NRC designation
  5424. athoncls endp
  5425.  
  5426. ; Display "LEDs" routine. yflags from MSYIBM is needed to know if the mode
  5427. ; line is enabled. Display current state of "LEDs" on line 25.
  5428. ansdsl    proc    near            ; display "LEDs"
  5429.     test    yflags,modoff        ; mode line off?
  5430.     jnz    ansdsl2            ; nz = yes, just return
  5431.     cmp    flags.modflg,1        ; mode line on and owned by us?
  5432.     jne    ansdsl2            ; ne = no, leave it intact
  5433.     mov    dh,byte ptr low_rgt+1    ; last screen line - 1
  5434.     inc    dh            ; status line
  5435.     mov    dl,led_col        ; column for led display
  5436.     call    setpos            ; set cursor position at (slen-1),70
  5437.     mov    cx,10            ; length of byte array is ten
  5438.     cld
  5439.     call    getled            ; set si to string, c set if no leds
  5440. ansdsl1:lodsb                ; get a character
  5441.     call    putchar            ; write character, increment cursor
  5442.     loop    ansdsl1            ; loop for all chars
  5443.     mov    dx,cursor        ; reposition cursor when finished
  5444.     push    dx
  5445.     call    direction        ; set dx to desired position
  5446.     call    setpos            ; set cursor position
  5447.     pop    dx
  5448. ansdsl2:ret
  5449. ansdsl    endp
  5450.  
  5451. ; Return pointer to "led" display in si, set carry if terminal type does
  5452. ; not have leds 1..4.
  5453. getled    proc    near
  5454.     mov    al,flags.vtflg        ; terminal type
  5455.     mov    si,offset v320leds    ; VT320 ident
  5456.     cmp    al,ttvt320        ; VT320?
  5457.     je    getled2            ; e = yes
  5458.     mov    si,offset v220leds    ; VT220 ident
  5459.     cmp    al,ttvt220        ; VT220?
  5460.     je    getled2            ; e = yes
  5461.     mov    si,offset v102leds    ; VT102 ident
  5462.     cmp    al,ttvt102        ; VT102 mode?
  5463.     je    getled2            ; e = yes
  5464.     mov    si,offset v100leds
  5465.     cmp    al,ttvt100        ; VT100?
  5466.     je    getled2            ; e = yes
  5467.     mov    si,offset honeyleds
  5468.     cmp    al,tthoney        ; Honeywell?
  5469.     je    getled2            ; e = yes
  5470.     mov    si,offset v52leds    ; VT52 ident
  5471.     cmp    al,ttvt52        ; VT52?
  5472.     je    getled1            ; e = yes, no leds
  5473.     mov    si,offset h19leds    ; Heath-19 ident
  5474. getled1:stc                ; c = set, does not have leds 1..4
  5475.     ret
  5476. getled2:clc                ; c = clear, has leds 1..4
  5477.     ret
  5478. getled    endp
  5479.  
  5480. ; This routine is called to adjust the cursor for the "indexing" like commands
  5481. ; (e.g., index, reverse index, newline, etc.).    It contrains the cursor, and
  5482. ; indicates if scrolling is necessary, and if so, in which direction.
  5483. ;
  5484. ; Call: cursor = "old" cursor position
  5485. ;    dx =     "new" cursor position
  5486. ;
  5487. ; Return: ax = pointer to scrolling routine to call (or to a ret)
  5488. ;      bx = "old" cursor position
  5489. ;      dx = "new" cursor position adjusted for screen limits or
  5490. ;               scrolling region, depending on whether the original
  5491. ;               cursor position was inside or outside the scrolling region.
  5492. ;
  5493. ; On the VT100, a scroll does not occur unless the original cursor position
  5494. ; was on the top or bottom margin. This routine assumes that when decom is
  5495. ; set the cursor position is set to the new origin, and that no other routine
  5496. ; allows the cursor to be positioned outside the scrolling region as long
  5497. ; as decom is set (which is the way a real VT100 works).  Note that for the
  5498. ; normal case (no limited scrolling region defined) the margins are the same
  5499. ; as the screen limits and scrolling occurs (as on a "normal" terminal) when
  5500. ; an attempt is made to index off the screen. Preserves cx.
  5501.  
  5502. atccic    proc    near
  5503.     push    cx
  5504.     mov    cl,byte ptr low_rgt    ; get right margin
  5505.     mov    bl,dh            ; get row
  5506.     xor    bh,bh
  5507.     cmp    bl,crt_lins        ; below screen?
  5508.     jae    atcci0            ; ae = yes, use single width line
  5509.     cmp    linetype[bx],0        ; single width chars?
  5510.     je    atcci0            ; e = yes, single width
  5511.     shr    cl,1            ; halve margin for double wides
  5512. atcci0:    mov    ax,offset atign        ; assume no scrolling necessary
  5513.     mov    bx,cursor        ; get old cursor
  5514.     cmp    dl,250            ; left of left margin? (wide screen)
  5515.     jb    atcci1            ; b = no, go check right
  5516.     xor    dl,dl            ; set to left margin
  5517. atcci1: cmp    dl,cl            ; right of right margin
  5518.     jbe    atcci2            ; be = yes, go check top
  5519.     mov    dl,cl            ; set to right margin
  5520. atcci2:    pop    cx
  5521.     cmp    bh,mar_top        ; was old pos above scroll top margin?
  5522.     jb    atcci7            ; b = yes
  5523.     cmp    dh,mar_top        ; want to go above top margin?
  5524.     jge    atcci5            ; ge = no
  5525.     mov    scroll,1
  5526.     mov    ax,offset atscrd    ; indicate scroll down required
  5527.     mov    dh,mar_top        ; set to top margin
  5528.     ret
  5529.  
  5530. atcci5:    cmp    bh,mar_bot        ; old position below bottom margin?
  5531.     ja    atcci7            ; a = yes
  5532.     cmp    dh,mar_bot        ; want to go below?
  5533.     jbe    atcci6            ; be = no, nothing to worry about
  5534.     mov    scroll,1        ; 1 line
  5535.     mov    ax,offset atscru    ; indicate scroll up required
  5536.     mov    dh,mar_bot        ; set to bottom margin
  5537. atcci6:    ret
  5538. atcci7:    jmp    short atccpc        ; old pos was outside scrolling region
  5539. atccic    endp
  5540.  
  5541. ; This routine is called to check the cursor position after any kind of cursor
  5542. ; positioning command.    Note that cursor positioning does NOT cause scrolling
  5543. ; on a VT100 (hence the need for a routine separate from this for "indexing".
  5544. ; Call:    dx = "new" cursor position (modified cursor)
  5545. ; Return: dx = "new" cursor position adjusted for screen limits (if
  5546. ;        decom is reset), or scrolling region (if decom is set).
  5547. ; Preserves ax, bx, and cx.
  5548.  
  5549. atccpc    proc    near
  5550.     push    bx            ; save bx and cx
  5551.     push    cx
  5552.     mov    cx,low_rgt        ; margins, cl = right margin
  5553.     mov    bl,dh            ; get row
  5554.     xor    bh,bh
  5555.     cmp    linetype [bx],0        ; single width line?
  5556.     je    atccp0            ; e = yes, single width
  5557.     shr    cl,1            ; halve right margin for double wides
  5558. atccp0:    cmp    dl,250            ; to left of left margin?(wide screen)
  5559.     jb    atccp1            ; b = no, go check right
  5560.     xor    dl,dl            ; set to left margin
  5561. atccp1: cmp    dl,cl            ; to right of right margin?
  5562.     jbe    atccp2            ; be = yes, go check top
  5563.     mov    dl,cl            ; set to right margin
  5564. atccp2:    pop    cx
  5565.     pop    bx
  5566.     test    vtemu.vtflgop,decom    ; Origin mode set?
  5567.     jnz    atccp5            ; nz = yes, stay in scrolling region
  5568.     or    dh,dh            ; above top of screen?
  5569.     jae    atccp3            ; ae = no, check bottom
  5570.     xor    dh,dh            ; stop here
  5571. atccp3: cmp    dh,byte ptr low_rgt+1    ; below bottom of screen?
  5572.     jbe    atccp4            ; be = no, stay in margins
  5573.     mov    dh,byte ptr low_rgt+1    ; "24th" line
  5574.     cmp    flags.vtflg,ttheath    ; Heath-19 mode?
  5575.     jne    atccp4            ; ne = no
  5576.     test    h19stat,h19l25        ; 25th line enabled?
  5577.     jnz    atccp4            ; nz = yes
  5578.     inc    dh            ; allow 25th line
  5579. atccp4:    ret
  5580.  
  5581. atccp5: cmp    dh,mar_top        ; above top of scrolling region?
  5582.     jae    atccp6            ; ae = no, check bottom
  5583.     mov    dh,mar_top        ; yes, stop there
  5584. atccp6: cmp    dh,mar_bot        ; below bottom perhaps?
  5585.     jbe    atccp4            ; be = no, return
  5586.     mov    dh,mar_bot        ; yes, stop at the bottom margin
  5587.     ret
  5588. atccpc    endp
  5589.  
  5590. ; Select Active Display. When selecting the status line make new scrolling
  5591. ; margins be just the status line and force on Origin mode. Save the regular
  5592. ; margins and origin mode for restoration when regular display is re-selected.
  5593. ; Also CSI Pn; Pn; Pn; Pn ~ invokes Lotus macro PRODUCT
  5594. atsasd    proc    near
  5595.     cmp    inter,'$'        ; correct intermediate?
  5596.     jne    atsasd1            ; ne = no
  5597.     cmp    param,1            ; select which display
  5598.     jb    atsasd4            ; b = select main display
  5599.     ja    atsasd1            ; a = illegal value
  5600.     cmp    flags.modflg,2        ; mode line host owned?
  5601.     jne    atsasd1            ; ne = no, ignore command
  5602.     test    dspstate,dsptype    ; was previous display = status line?
  5603.     jz    atsasd2            ; z = no
  5604. atsasd1:ret                ; else do nothing
  5605.  
  5606. atsasd2:push    word ptr mar_top    ; save scrolling margins
  5607.     pop    dspmsave        ; save scrolling margins
  5608.     or    dspstate,dsptype    ; say status line is active
  5609.     mov    al,byte ptr low_rgt+1    ; get last text line
  5610.     inc    al            ; status line
  5611.     mov    mar_top,al
  5612.     mov    mar_bot,al        ; new scrolling margins
  5613.     and    dspstate,not dspdecom    ; clear remembered origin mode
  5614.     test    vtemu.vtflgop,decom    ; was origin mode active?
  5615.     jz    atsasd3            ; z = no
  5616.     or    dspstate,dspdecom    ; remember origin mode was active
  5617. atsasd3:or    vtemu.vtflgop,decom    ; set origin mode
  5618.     push    cursor            ; get current main display cursor
  5619.     pop    dspcmain        ; save it
  5620.     mov    dx,dspcstat        ; get status line cursor
  5621.     mov    dh,mar_top        ; set row
  5622.     jmp    atscu5            ; set cursor
  5623.  
  5624. atsasd4:test    dspstate,dsptype    ; was previous display = status line?
  5625.     jnz    atsasd5            ; nz = yes
  5626.     ret                ; else do nothing    
  5627. atsasd5:push    dspmsave        ; restore scrolling margins
  5628.     pop    word ptr mar_top
  5629.     and    vtemu.vtflgop,not decom    ; clear origin mode bit
  5630.     test    dspstate,dspdecom    ; was origin mode on for main screen?
  5631.     jz    atsasd6            ; z = no
  5632.     or    vtemu.vtflgop,decom    ; set it now
  5633. atsasd6:push    cursor            ; get status line cursor position
  5634.     pop    dspcstat        ; save it
  5635.     mov    dx,dspcmain        ; get saved cursor position
  5636.     mov    dspstate,0        ; say now doing main screen
  5637.     jmp    atscu5            ; set cursor
  5638. atsasd    endp
  5639.  
  5640. atssdt    proc    near            ; Select Status Line Type, DECSSDT
  5641.     cmp    inter,'$'        ; correct intermediate char?
  5642.     je    atssdt1            ; e = yes
  5643.     cmp    ninter,0        ; no intermediates?
  5644.     jne    atssdt0            ; ne = no
  5645.     jmp    product            ; do product macro
  5646. atssdt0:ret
  5647. atssdt1:test    dspstate,dsptype    ; on mode line already?
  5648.     jnz    atssdt4            ; nz = yes, cannot reselect now
  5649.     cmp    param,0            ; turn off status line?
  5650.     jne    atssdt2            ; ne = no
  5651.     push    dx            ; save cursor position
  5652.     call    clrmod            ; clear the line
  5653.     pop    dx
  5654.     or    yflags,modoff        ; now say it's off
  5655.     mov    flags.modflg,1        ; say mode line is owned by us
  5656.     ret
  5657. atssdt2:cmp    param,1            ; regular status line?
  5658.     jne    atssdt3
  5659.     push    dx
  5660.     call    modlin            ; turn on regular mode line
  5661.     pop    dx
  5662.     and    yflags,not modoff    ; and say it's on
  5663.     mov    flags.modflg,1        ; say mode line is owned by us
  5664.     ret
  5665. atssdt3:cmp    param,2            ; host writable?
  5666.     jne    atssdt4            ; ne = no
  5667.     mov    flags.modflg,2        ; say mode line is owned by host
  5668. atssdt4:ret
  5669. atssdt    endp
  5670.  
  5671. ; Routine to set cursor type (off, block, underline).
  5672.  
  5673. atsctyp:cmp    flags.vtflg,ttheath    ; Heath-19?
  5674.     jne    atsct1            ; ne = no
  5675.     mov    al,h19ctyp        ; get cursor kind and on/off bit
  5676.     test    al,4            ; is cursor to be off?
  5677.     jz    atsct4            ; z = no, al has kind
  5678.     xor    al,al            ; turn off cursor
  5679.     jmp    short atsct4        ; do it
  5680. atsct1:    test    atctype,4        ; VTxxx cursor type, off?
  5681.     jz    atsct2            ; z = no
  5682.     xor    al,al
  5683.     jmp    short atsct4        ; turn it off
  5684. atsct2:    mov    al,1            ; assume underline
  5685.     test    vtemu.vtflgop,vscursor    ; block?
  5686.     jnz    atsct3            ; nz = no, underline
  5687.     mov    al,2
  5688. atsct3:    mov    atctype,al        ; save VTxxx cursor type here
  5689. atsct4:    call    csrtype            ; set the cursor type
  5690.     ret
  5691.  
  5692. atdeb    proc    near            ; Debug, display all chars in tty style
  5693.     test    yflags,capt        ; capturing output?
  5694.     jz    atdeb3            ; z = no, forget this part
  5695.     call    cptchr            ; give it captured character
  5696. atdeb3:    mov    bl,curattr        ; save attribute
  5697.     push    bx
  5698.     push    word ptr mar_top    ; save limited scrolling region
  5699.     push    ax            ; save character for a second
  5700.     mov    ah,curattr        ; get attribute
  5701.     call    clrblink        ; clear blink attribute
  5702.     call    clrunder        ; clear underline attribute
  5703.     mov    curattr,ah        ; store
  5704.     or    vtemu.vtflgop,decawm    ; set autowrap temporarily
  5705.     mov    mar_top,0        ; set scrolling region to entire page
  5706.     mov    al,byte ptr low_rgt+1
  5707.     mov    mar_bot,al
  5708.     pop    ax            ; restore character
  5709.     test    al,80h            ; high bit set?
  5710.     jz    atdeb0            ; z = not set
  5711.     push    ax            ; save the character for a second
  5712.     mov    al,7eh            ; output a tilde
  5713.     call    atnrm2
  5714.     pop    ax            ; restore character
  5715.     and    al,7fh            ; and remove high bit
  5716. atdeb0:    cmp    al,del            ; DELETE?
  5717.     je    atdeb1            ; e = yes, output "^?"
  5718.     cmp    al,20h            ; control character?
  5719.     jnb    atdeb2            ; nb = no, just output char in al
  5720. atdeb1: push    ax            ; save the character for a second
  5721.     mov    al,5eh            ; output a caret
  5722.     call    atnrm2
  5723.     pop    ax            ; restore character
  5724.     add    al,40h            ; make ^letter (or ^? for DELETE)
  5725.     and    al,7fh            ; clear bit 7 (for DELETE)
  5726. atdeb2: call    atnrm2            ; output translated character
  5727.     pop    word ptr mar_top    ; restore scrolling region,
  5728.     pop    bx            ;  flags, and cursor attribute
  5729.     mov    curattr,bl
  5730.     ret
  5731. atdeb    endp
  5732. code    ends
  5733.     end
  5734.